<!DOCTYPE html><html lang="zh-CN" data-theme="light"><head><meta charset="UTF-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no"><title>Docker | 樱桃小窝</title><meta name="keywords" content="Docker"><meta name="author" content="樱桃先生"><meta name="copyright" content="樱桃先生"><meta name="format-detection" content="telephone=no"><meta name="theme-color" content="#ffffff"><meta name="description" content="常用命令直接跳至”Docker的常用命令” 查询常用命令直接跳至”Docker的常用命令” 配置阿里云镜像: yum-config-manager –add-repo http:&#x2F;&#x2F;mirrors.aliyun.com&#x2F;docker-ce&#x2F;linux&#x2F;centos&#x2F;docker-ce.repo 前面章节为官方文档翻译 后面为常用操作和自启设置  Docker是什么？系统平滑移植，容器虚拟化技术">
<meta property="og:type" content="article">
<meta property="og:title" content="Docker">
<meta property="og:url" content="http://example.com/posts/f5f9fa9b/index.html">
<meta property="og:site_name" content="樱桃小窝">
<meta property="og:description" content="常用命令直接跳至”Docker的常用命令” 查询常用命令直接跳至”Docker的常用命令” 配置阿里云镜像: yum-config-manager –add-repo http:&#x2F;&#x2F;mirrors.aliyun.com&#x2F;docker-ce&#x2F;linux&#x2F;centos&#x2F;docker-ce.repo 前面章节为官方文档翻译 后面为常用操作和自启设置  Docker是什么？系统平滑移植，容器虚拟化技术">
<meta property="og:locale" content="zh_CN">
<meta property="og:image" content="https://ytblogpic.oss-cn-guangzhou.aliyuncs.com/typorau=2532140561,3610048596&fm=26&gp=0.jpg">
<meta property="article:published_time" content="2020-09-09T13:45:00.000Z">
<meta property="article:modified_time" content="2022-09-01T14:08:39.988Z">
<meta property="article:author" content="樱桃先生">
<meta property="article:tag" content="Docker">
<meta name="twitter:card" content="summary">
<meta name="twitter:image" content="https://ytblogpic.oss-cn-guangzhou.aliyuncs.com/typorau=2532140561,3610048596&fm=26&gp=0.jpg"><link rel="shortcut icon" href="/img/favicon.png"><link rel="canonical" href="http://example.com/posts/f5f9fa9b/"><link rel="preconnect" href="//cdn.jsdelivr.net"/><link rel="preconnect" href="//busuanzi.ibruce.info"/><link rel="stylesheet" href="/css/index.css"><link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@fortawesome/fontawesome-free/css/all.min.css" media="print" onload="this.media='all'"><link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@fancyapps/ui/dist/fancybox.min.css" media="print" onload="this.media='all'"><script>const GLOBAL_CONFIG = { 
  root: '/',
  algolia: undefined,
  localSearch: undefined,
  translate: undefined,
  noticeOutdate: undefined,
  highlight: {"plugin":"highlighjs","highlightCopy":true,"highlightLang":true,"highlightHeightLimit":false},
  copy: {
    success: '复制成功',
    error: '复制错误',
    noSupport: '浏览器不支持'
  },
  relativeDate: {
    homepage: false,
    post: false
  },
  runtime: '天',
  date_suffix: {
    just: '刚刚',
    min: '分钟前',
    hour: '小时前',
    day: '天前',
    month: '个月前'
  },
  copyright: undefined,
  lightbox: 'fancybox',
  Snackbar: undefined,
  source: {
    justifiedGallery: {
      js: 'https://cdn.jsdelivr.net/npm/flickr-justified-gallery/dist/fjGallery.min.js',
      css: 'https://cdn.jsdelivr.net/npm/flickr-justified-gallery/dist/fjGallery.min.css'
    }
  },
  isPhotoFigcaption: false,
  islazyload: true,
  isAnchor: false
}</script><script id="config-diff">var GLOBAL_CONFIG_SITE = {
  title: 'Docker',
  isPost: true,
  isHome: false,
  isHighlightShrink: false,
  isToc: true,
  postUpdate: '2022-09-01 22:08:39'
}</script><noscript><style type="text/css">
  #nav {
    opacity: 1
  }
  .justified-gallery img {
    opacity: 1
  }

  #recent-posts time,
  #post-meta time {
    display: inline !important
  }
</style></noscript><script>(win=>{
    win.saveToLocal = {
      set: function setWithExpiry(key, value, ttl) {
        if (ttl === 0) return
        const now = new Date()
        const expiryDay = ttl * 86400000
        const item = {
          value: value,
          expiry: now.getTime() + expiryDay,
        }
        localStorage.setItem(key, JSON.stringify(item))
      },

      get: function getWithExpiry(key) {
        const itemStr = localStorage.getItem(key)

        if (!itemStr) {
          return undefined
        }
        const item = JSON.parse(itemStr)
        const now = new Date()

        if (now.getTime() > item.expiry) {
          localStorage.removeItem(key)
          return undefined
        }
        return item.value
      }
    }
  
    win.getScript = url => new Promise((resolve, reject) => {
      const script = document.createElement('script')
      script.src = url
      script.async = true
      script.onerror = reject
      script.onload = script.onreadystatechange = function() {
        const loadState = this.readyState
        if (loadState && loadState !== 'loaded' && loadState !== 'complete') return
        script.onload = script.onreadystatechange = null
        resolve()
      }
      document.head.appendChild(script)
    })
  
      win.activateDarkMode = function () {
        document.documentElement.setAttribute('data-theme', 'dark')
        if (document.querySelector('meta[name="theme-color"]') !== null) {
          document.querySelector('meta[name="theme-color"]').setAttribute('content', '#0d0d0d')
        }
      }
      win.activateLightMode = function () {
        document.documentElement.setAttribute('data-theme', 'light')
        if (document.querySelector('meta[name="theme-color"]') !== null) {
          document.querySelector('meta[name="theme-color"]').setAttribute('content', '#ffffff')
        }
      }
      const t = saveToLocal.get('theme')
    
          if (t === 'dark') activateDarkMode()
          else if (t === 'light') activateLightMode()
        
      const asideStatus = saveToLocal.get('aside-status')
      if (asideStatus !== undefined) {
        if (asideStatus === 'hide') {
          document.documentElement.classList.add('hide-aside')
        } else {
          document.documentElement.classList.remove('hide-aside')
        }
      }
    
    const detectApple = () => {
      if(/iPad|iPhone|iPod|Macintosh/.test(navigator.userAgent)){
        document.documentElement.classList.add('apple')
      }
    }
    detectApple()
    })(window)</script><meta name="generator" content="Hexo 5.4.2"></head><body><div id="sidebar"><div id="menu-mask"></div><div id="sidebar-menus"><div class="avatar-img is-center"><img src= "" data-lazy-src="https://s2.loli.net/2022/08/20/hk9Zvq4YRsIcnrw.jpg" onerror="onerror=null;src='/img/friend_404.gif'" alt="avatar"/></div><div class="sidebar-site-data site-data is-center"><a href="/archives/"><div class="headline">文章</div><div class="length-num">78</div></a><a href="/tags/"><div class="headline">标签</div><div class="length-num">65</div></a><a href="/categories/"><div class="headline">分类</div><div class="length-num">21</div></a></div><hr/><div class="menus_items"><div class="menus_item"><a class="site-page" href="/"><i class="fa-fw fas fa-home"></i><span> 主页</span></a></div><div class="menus_item"><a class="site-page" href="/archives/"><i class="fa-fw fas fa-archive"></i><span> 时间线</span></a></div><div class="menus_item"><a class="site-page" href="/categories/"><i class="fa-fw fas fa-folder-open"></i><span> 分类</span></a></div><div class="menus_item"><a class="site-page" href="/tags/"><i class="fa-fw fas fa-tags"></i><span> 标签</span></a></div><div class="menus_item"><a class="site-page" href="/gallery/"><i class="fa-fw fas fa-camera"></i><span> 图库</span></a></div><div class="menus_item"><a class="site-page" href="/messageboard/"><i class="fa-fw fas fa-comment-dots"></i><span> 留言板</span></a></div><div class="menus_item"><a class="site-page" href="/links/"><i class="fa-fw fas fa-link"></i><span> 友链</span></a></div><div class="menus_item"><a class="site-page" href="/about/"><i class="fa-fw fas fa-heart"></i><span> 关于</span></a></div></div></div></div><div class="post" id="body-wrap"><header class="post-bg" id="page-header" style="background-image: url('https://ytblogpic.oss-cn-guangzhou.aliyuncs.com/typorau=2532140561,3610048596&amp;fm=26&amp;gp=0.jpg')"><nav id="nav"><span id="blog_name"><a id="site-name" href="/">樱桃小窝</a></span><div id="menus"><div class="menus_items"><div class="menus_item"><a class="site-page" href="/"><i class="fa-fw fas fa-home"></i><span> 主页</span></a></div><div class="menus_item"><a class="site-page" href="/archives/"><i class="fa-fw fas fa-archive"></i><span> 时间线</span></a></div><div class="menus_item"><a class="site-page" href="/categories/"><i class="fa-fw fas fa-folder-open"></i><span> 分类</span></a></div><div class="menus_item"><a class="site-page" href="/tags/"><i class="fa-fw fas fa-tags"></i><span> 标签</span></a></div><div class="menus_item"><a class="site-page" href="/gallery/"><i class="fa-fw fas fa-camera"></i><span> 图库</span></a></div><div class="menus_item"><a class="site-page" href="/messageboard/"><i class="fa-fw fas fa-comment-dots"></i><span> 留言板</span></a></div><div class="menus_item"><a class="site-page" href="/links/"><i class="fa-fw fas fa-link"></i><span> 友链</span></a></div><div class="menus_item"><a class="site-page" href="/about/"><i class="fa-fw fas fa-heart"></i><span> 关于</span></a></div></div><div id="toggle-menu"><a class="site-page"><i class="fas fa-bars fa-fw"></i></a></div></div></nav><div id="post-info"><h1 class="post-title">Docker</h1><div id="post-meta"><div class="meta-firstline"><span class="post-meta-date"><i class="far fa-calendar-alt fa-fw post-meta-icon"></i><span class="post-meta-label">发表于</span><time class="post-meta-date-created" datetime="2020-09-09T13:45:00.000Z" title="发表于 2020-09-09 21:45:00">2020-09-09</time><span class="post-meta-separator">|</span><i class="fas fa-history fa-fw post-meta-icon"></i><span class="post-meta-label">更新于</span><time class="post-meta-date-updated" datetime="2022-09-01T14:08:39.988Z" title="更新于 2022-09-01 22:08:39">2022-09-01</time></span><span class="post-meta-categories"><span class="post-meta-separator">|</span><i class="fas fa-inbox fa-fw post-meta-icon"></i><a class="post-meta-categories" href="/categories/%E6%8A%80%E6%9C%AF/">技术</a></span></div><div class="meta-secondline"><span class="post-meta-separator">|</span><span class="post-meta-pv-cv" id="" data-flag-title="Docker"><i class="far fa-eye fa-fw post-meta-icon"></i><span class="post-meta-label">阅读量:</span><span id="busuanzi_value_page_pv"><i class="fa-solid fa-spinner fa-spin"></i></span></span></div></div></div></header><main class="layout" id="content-inner"><div id="post"><article class="post-content" id="article-container"><blockquote>
<p>常用命令直接跳至”Docker的常用命令”</p>
<p>查询常用命令直接跳至”Docker的常用命令”</p>
<p>配置阿里云镜像:</p>
<p>yum-config-manager –add-repo <a target="_blank" rel="noopener" href="http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo">http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo</a></p>
<p>前面章节为官方文档翻译 后面为常用操作和自启设置</p>
</blockquote>
<h1 id="Docker"><a href="#Docker" class="headerlink" title="Docker"></a>Docker</h1><h2 id="是什么？"><a href="#是什么？" class="headerlink" title="是什么？"></a>是什么？</h2><p>系统平滑移植，容器虚拟化技术</p>
<p>Docker 是一个开源项目，诞生于 2013 年初，最初是 dotCloud 公司内部的一个业余项目。它基于 Google 公司推出的 Go 语言实现。 项目后来加入了 Linux 基金会，遵从了 Apache 2.0 协议，项目代码在 GitHub 上进行维护。</p>
<p>Docker 自开源后受到广泛的关注和讨论，以至于 dotCloud 公司后来都改名为 Docker Inc。Redhat 已经在其 RHEL6.5 中集中支持 Docker；Google 也在其 PaaS 产品中广泛应用。</p>
<p>Docker 项目的目标是实现<strong>轻量级</strong>的<strong>操作系统虚拟化</strong>解决方案。 Docker 的基础是 <strong>Linux 容器（LXC）</strong>等技术。</p>
<p>在 LXC 的基础上 Docker 进行了进一步的封装，让用户不需要去关心容器的管理，使得操作更为简便。用户操作 Docker 的容器就像操作一个快速轻量级的虚拟机一样简单。</p>
<p>下面的图片比较了 Docker 和传统虚拟化方式的不同之处，可见<strong>容器是在操作系统层面</strong>上实现虚拟化，直接复用本地主机的操作系统，而<strong>传统方式则是在硬件层面</strong>实现。</p>
<p><img src= "" data-lazy-src="https://ytblogpic.oss-cn-guangzhou.aliyuncs.com/typoravirtualization.png" alt="传统虚拟化"></p>
<p><img src= "" data-lazy-src="https://gitee.com/xyingtao/blogimage/raw/master/img/docker.png" alt="Docker"></p>
<h1 id="应用场景"><a href="#应用场景" class="headerlink" title="应用场景"></a>应用场景</h1><ul>
<li>web应用的自动化打包和发布；</li>
<li>自动化测试和持续集成、发布；</li>
<li>在服务型环境中部署和调整数据库或其他的后台应用；</li>
<li>从头编译或者扩展现有的OpenShift或Cloud Foundry平台来搭建自己的PaaS环境。</li>
</ul>
<h2 id="在任何地方开发、部署和运行任何应用"><a href="#在任何地方开发、部署和运行任何应用" class="headerlink" title="在任何地方开发、部署和运行任何应用"></a>在任何地方开发、部署和运行任何应用</h2><blockquote>
<p>Docker是一款针对程序开发人员和系统管理员来开发、部署、运行应用的一款虚拟化平台。Docker 可以让你像使用集装箱一样快速的组合成应用，并且可以像运输标准集装箱一样，尽可能的屏蔽代码层面的差异。Docker 会尽可能的缩短从代码测试到产品部署的时间。</p>
</blockquote>
<p>Docker 组件</p>
<ul>
<li>The Docker Engine – Docker Engine 是一个基于虚拟化技术的轻量级并且功能强大的开源容器引擎管理工具。它可以将不同的 work flow 组合起来构建成你的应用。</li>
<li>Docker Hub 可以分享和管理你的images镜像的一个 Saas 服务。</li>
</ul>
<h3 id="为什么选择Docker"><a href="#为什么选择Docker" class="headerlink" title="为什么选择Docker"></a>为什么选择Docker</h3><h3 id="快速交付应用程序"><a href="#快速交付应用程序" class="headerlink" title="快速交付应用程序"></a>快速交付应用程序</h3><ul>
<li>我们希望你的开发环境能够更好的提高你的工作效率。Docker容器能够帮助开发人员、系统管理员、QA和版本控制工程师在一个生产环节中一起协同工作。我们制定了一套容器标准，而这套容器标准能够使系统管理员更改容器的时候，程序员不需要关心容器的变化，而更专注自己的应用程序代码。从而隔离开了开发和管理，简化了开发和部署的成本。</li>
<li>我们使应用的构建方式更加简单，可以快速的迭代你的应用，并且可以可视化的来查看应用的细微更改。这能够帮助组织里边的成员来更好的理解一个应用从构建到运行的过程。</li>
<li>Docker 是一个轻量级的容器，所以它的速度是非常快的，而容器的启动时间只需要一秒钟，从而大大的减少了开发、测试和部署的时间。轻松部署和扩展</li>
<li>Docker 容器可以运行在大多数的环境中，你可以在桌面环境、物理主机、虚拟主机再到数据中，私有或者公有云中部署。</li>
<li>因为 Docker 可以从多平台下运行。你可以很容器的迁移你的应用程序。如果需要，你可以非常简单的将应用程序从测试环境迁移到云，或者从云迁移到测试环境。</li>
<li>Docker 是一个轻量级的容器，因此它可以在很短的时间内启动和关闭。当你需要的时候，你可以启动多个容器引擎，并且在不需要使用他们的时候，可以将他们全部关闭。</li>
</ul>
<p>Docker的容器本身不需要额外创建虚拟机管理系统，因此你可以启动多套Docker容器，这样就可以充分发挥主机服务器的物理资源，也可以降低因为采购服务器licenses而带来的额外成本。</p>
<h3 id="快速构建-轻松管理"><a href="#快速构建-轻松管理" class="headerlink" title="快速构建 轻松管理"></a>快速构建 轻松管理</h3><p>因为Docker上述轻便，快速的特性。可以使您的应用达到快速迭代的目的。每次小的变更，马上就可以看到效果。而不用将若干个小变更积攒到一定程度再变更。每次变更一小部分其实是一种非常安全的方式。</p>
<h1 id="Image镜像"><a href="#Image镜像" class="headerlink" title="Image镜像"></a>Image镜像</h1><h2 id="介绍"><a href="#介绍" class="headerlink" title="介绍"></a>介绍</h2><p><img src= "" data-lazy-src="https://ytblogpic.oss-cn-guangzhou.aliyuncs.com/typoradocker-filesystems-debian.png" alt="基础镜像"></p>
<p>在 Docker 的术语里，一个只读层被称为镜像，一个镜像是永久不会变的。</p>
<p>由于 Docker 使用一个统一文件系统，Docker 进程认为整个文件系统是以读写方式挂载的。 但是所有的变更都发生顶层的可写层，而下层的原始的只读镜像文件并未变化。由于镜像不 可写，所以镜像是无状态的。</p>
<p><img src= "" data-lazy-src="https://ytblogpic.oss-cn-guangzhou.aliyuncs.com/typoradocker-filesystems-debianrw.png" alt="镜像可写层"></p>
<h3 id="父镜像"><a href="#父镜像" class="headerlink" title="父镜像"></a>父镜像</h3><p><img src= "" data-lazy-src="https://ytblogpic.oss-cn-guangzhou.aliyuncs.com/typoradocker-filesystems-multilayer.png" alt="镜像层次"></p>
<p>每一个镜像都可能依赖于由一个或多个下层的组成的另一个镜像。我们有时说，下层那个 镜像是上层镜像的父镜像。</p>
<h3 id="基础镜像"><a href="#基础镜像" class="headerlink" title="基础镜像"></a>基础镜像</h3><p>一个没有任何父镜像的镜像，谓之基础镜像。</p>
<h3 id="镜像ID"><a href="#镜像ID" class="headerlink" title="镜像ID"></a>镜像ID</h3><p>所有镜像都是通过一个 64 位十六进制字符串 （内部是一个 256 bit 的值）来标识的。 为简化使用，前 12 个字符可以组成一个短ID，可以在命令行中使用。短ID还是有一定的 碰撞机率，所以服务器总是返回长ID。</p>
<h2 id="获取镜像"><a href="#获取镜像" class="headerlink" title="获取镜像"></a>获取镜像</h2><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">docker pull</span><br></pre></td></tr></table></figure>

<p>国内要配置镜像加速</p>
<h2 id="列出本地镜像"><a href="#列出本地镜像" class="headerlink" title="列出本地镜像"></a>列出本地镜像</h2><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">docker images</span><br></pre></td></tr></table></figure>

<p>在列出信息中，可以看到几个字段信息</p>
<ul>
<li>来自于哪个仓库，比如 ubuntu</li>
<li><code>TAG</code> 信息,镜像的标记，比如 14.04,区分发行版本</li>
<li>它的 <code>ID</code> 号（唯一）</li>
<li>创建时间</li>
<li>镜像大小</li>
</ul>
<p>如果不指定具体的标记，则默认使用 <code>latest</code> 标记信息。</p>
<h2 id="创建镜像"><a href="#创建镜像" class="headerlink" title="创建镜像"></a>创建镜像</h2><p>创建镜像有很多方法，用户可以从 Docker Hub 获取已有镜像并更新，也可以利用本地文件系统创建一个。</p>
<h3 id="修改已有镜像"><a href="#修改已有镜像" class="headerlink" title="修改已有镜像"></a>修改已有镜像</h3><p>先使用下载的镜像启动容器。</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">$ sudo docker run -t -i training/sinatra /bin/bash</span><br><span class="line">root@0b2616b0e5a8:/#</span><br></pre></td></tr></table></figure>

<p>注意：记住容器的 ID，稍后还会用到。</p>
<p>在容器中添加 json 和 gem 两个应用。</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">root@0b2616b0e5a8:/# gem install json</span><br></pre></td></tr></table></figure>

<p>当结束后，我们使用 exit 来退出，现在我们的容器已经被我们改变了，使用 <code>docker commit</code> 命令来提交更新后的副本。</p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">$ sudo docker commit -m <span class="string">&quot;Added json gem&quot;</span> -a <span class="string">&quot;Docker Newbee&quot;</span> 0b2616b0e5a8 ouruser/sinatra:v2</span><br><span class="line">4f177bd27a9ff0f6dc2a830403925b5360bfe0b93d476f7fc3231110e7f71b1c</span><br></pre></td></tr></table></figure>

<p>其中，<code>-m</code> 来指定提交的说明信息，跟我们使用的版本控制工具一样；<code>-a</code> 可以指定更新的用户信息；之后是用来创建镜像的容器的 ID；最后指定目标镜像的仓库名和 tag 信息。创建成功后会返回这个镜像的 ID 信息。</p>
<p>使用 <code>docker images</code> 来查看新创建的镜像。</p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">$ sudo docker images</span><br><span class="line">REPOSITORY          TAG     IMAGE ID       CREATED       VIRTUAL SIZE</span><br><span class="line">training/sinatra    latest  5bc342fa0b91   10 hours ago  446.7 MB</span><br><span class="line">ouruser/sinatra     v2      3c59e02ddd1a   10 hours ago  446.7 MB</span><br><span class="line">ouruser/sinatra     latest  5db5f8471261   10 hours ago  446.7 MB</span><br></pre></td></tr></table></figure>

<p>之后，可以使用新的镜像来启动容器</p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">$ sudo docker run -t -i ouruser/sinatra:v2 /bin/bash</span><br><span class="line">root@78e82f680994:/<span class="comment">#</span></span><br></pre></td></tr></table></figure>

<h3 id="利用-Dockerfile-来创建镜像"><a href="#利用-Dockerfile-来创建镜像" class="headerlink" title="利用 Dockerfile 来创建镜像"></a>利用 Dockerfile 来创建镜像</h3><p>使用 <code>docker commit</code> 来扩展一个镜像比较简单，但是不方便在一个团队中分享。我们可以使用 <code>docker build</code>来创建一个新的镜像。为此，首先需要创建一个 Dockerfile，包含一些如何创建镜像的指令。</p>
<p>新建一个目录和一个 Dockerfile</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">$ mkdir sinatra</span><br><span class="line">$ cd sinatra</span><br><span class="line">$ touch Dockerfile</span><br></pre></td></tr></table></figure>

<p>Dockerfile 中每一条指令都创建镜像的一层，例如：</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"># This is a comment</span><br><span class="line">FROM ubuntu:14.04</span><br><span class="line">MAINTAINER Docker Newbee &lt;newbee@docker.com&gt;</span><br><span class="line">RUN apt-get -qq update</span><br><span class="line">RUN apt-get -qqy install ruby ruby-dev</span><br><span class="line">RUN gem install sinatra</span><br></pre></td></tr></table></figure>

<p>Dockerfile 基本的语法是</p>
<ul>
<li>使用<code>#</code>来注释</li>
<li><code>FROM</code> 指令告诉 Docker 使用哪个镜像作为基础</li>
<li>接着是维护者的信息</li>
<li><code>RUN</code>开头的指令会在创建中运行，比如安装一个软件包，在这里使用 apt-get 来安装了一些软件</li>
</ul>
<p>编写完成 Dockerfile 后可以使用 <code>docker build</code> 来生成镜像。</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br></pre></td><td class="code"><pre><span class="line">$ sudo docker build -t=&quot;ouruser/sinatra:v2&quot; .</span><br><span class="line">Uploading context  2.56 kB</span><br><span class="line">Uploading context</span><br><span class="line">Step 0 : FROM ubuntu:14.04</span><br><span class="line"> ---&gt; 99ec81b80c55</span><br><span class="line">Step 1 : MAINTAINER Newbee &lt;newbee@docker.com&gt;</span><br><span class="line"> ---&gt; Running in 7c5664a8a0c1</span><br><span class="line"> ---&gt; 2fa8ca4e2a13</span><br><span class="line">Removing intermediate container 7c5664a8a0c1</span><br><span class="line">Step 2 : RUN apt-get -qq update</span><br><span class="line"> ---&gt; Running in b07cc3fb4256</span><br><span class="line"> ---&gt; 50d21070ec0c</span><br><span class="line">Removing intermediate container b07cc3fb4256</span><br><span class="line">Step 3 : RUN apt-get -qqy install ruby ruby-dev</span><br><span class="line"> ---&gt; Running in a5b038dd127e</span><br><span class="line">Selecting previously unselected package libasan0:amd64.</span><br><span class="line">(Reading database ... 11518 files and directories currently installed.)</span><br><span class="line">Preparing to unpack .../libasan0_4.8.2-19ubuntu1_amd64.deb ...</span><br><span class="line">Setting up ruby (1:1.9.3.4) ...</span><br><span class="line">Setting up ruby1.9.1 (1.9.3.484-2ubuntu1) ...</span><br><span class="line">Processing triggers for libc-bin (2.19-0ubuntu6) ...</span><br><span class="line"> ---&gt; 2acb20f17878</span><br><span class="line">Removing intermediate container a5b038dd127e</span><br><span class="line">Step 4 : RUN gem install sinatra</span><br><span class="line"> ---&gt; Running in 5e9d0065c1f7</span><br><span class="line">. . .</span><br><span class="line">Successfully installed rack-protection-1.5.3</span><br><span class="line">Successfully installed sinatra-1.4.5</span><br><span class="line">4 gems installed</span><br><span class="line"> ---&gt; 324104cde6ad</span><br><span class="line">Removing intermediate container 5e9d0065c1f7</span><br><span class="line">Successfully built 324104cde6ad</span><br></pre></td></tr></table></figure>

<p>其中 <code>-t</code> 标记来添加 tag，指定新的镜像的用户信息。 “.” 是 Dockerfile 所在的路径（当前目录），也可以替换为一个具体的 Dockerfile 的路径。</p>
<p>可以看到 build 进程在执行操作。它要做的第一件事情就是上传这个 Dockerfile 内容，因为所有的操作都要依据  Dockerfile 来进行。 然后，Dockfile  中的指令被一条一条的执行。每一步都创建了一个新的容器，在容器中执行指令并提交修改（就跟之前介绍过的 <code>docker commit</code> 一样）。当所有的指令都执行完毕之后，返回了最终的镜像 id。所有的中间步骤所产生的容器都被删除和清理了。</p>
<p>*注意一个镜像不能超过 127 层</p>
<p>此外，还可以利用 <code>ADD</code> 命令复制本地文件到镜像；用 <code>EXPOSE</code> 命令来向外部开放端口；用 <code>CMD</code> 命令来描述容器启动后运行的程序等。例如</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"># put my local web site in myApp folder to /var/www</span><br><span class="line">ADD myApp /var/www</span><br><span class="line"># expose httpd port</span><br><span class="line">EXPOSE 80</span><br><span class="line"># the command to run</span><br><span class="line">CMD [&quot;/usr/sbin/apachectl&quot;, &quot;-D&quot;, &quot;FOREGROUND&quot;]</span><br></pre></td></tr></table></figure>

<p>现在可以利用新创建的镜像来启动一个容器。</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">$ sudo docker run -t -i ouruser/sinatra:v2 /bin/bash</span><br><span class="line">root@8196968dac35:/#</span><br></pre></td></tr></table></figure>

<p>还可以用 <code>docker tag</code> 命令来修改镜像的标签。</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">$ sudo docker tag 5db5f8471261 ouruser/sinatra:devel</span><br><span class="line">$ sudo docker images ouruser/sinatra</span><br><span class="line">REPOSITORY          TAG     IMAGE ID      CREATED        VIRTUAL SIZE</span><br><span class="line">ouruser/sinatra     latest  5db5f8471261  11 hours ago   446.7 MB</span><br><span class="line">ouruser/sinatra     devel   5db5f8471261  11 hours ago   446.7 MB</span><br><span class="line">ouruser/sinatra     v2      5db5f8471261  11 hours ago   446.7 MB</span><br></pre></td></tr></table></figure>

<h3 id="从本地文件系统导入"><a href="#从本地文件系统导入" class="headerlink" title="从本地文件系统导入"></a>从本地文件系统导入</h3><p>要从本地文件系统导入一个镜像，可以使用 openvz（容器虚拟化的先锋技术）的模板来创建： openvz 的模板下载地址为 templates 。</p>
<p>比如，先下载了一个 ubuntu-14.04 的镜像，之后使用以下命令导入：</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">sudo cat ubuntu-14.04-x86_64-minimal.tar.gz  |docker import - ubuntu:14.04</span><br></pre></td></tr></table></figure>

<p>然后查看新导入的镜像。</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">docker images</span><br><span class="line">REPOSITORY          TAG                 IMAGE ID            CREATED             VIRTUAL SIZE</span><br><span class="line">ubuntu              14.04               05ac7c0b9383        17 seconds ago      215.5 MB</span><br></pre></td></tr></table></figure>

<h3 id="上传镜像"><a href="#上传镜像" class="headerlink" title="上传镜像"></a>上传镜像</h3><p>用户可以通过 <code>docker push</code> 命令，把自己创建的镜像上传到仓库中来共享。例如，用户在 Docker Hub 上完成注册后，可以推送自己的镜像到仓库中。</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">$ sudo docker push ouruser/sinatra</span><br><span class="line">The push refers to a repository [ouruser/sinatra] (len: 1)</span><br><span class="line">Sending image list</span><br><span class="line">Pushing repository ouruser/sinatra (3 tags)</span><br></pre></td></tr></table></figure>

<h2 id="存出和载入镜像"><a href="#存出和载入镜像" class="headerlink" title="存出和载入镜像"></a>存出和载入镜像</h2><h3 id="存出镜像"><a href="#存出镜像" class="headerlink" title="存出镜像"></a>存出镜像</h3><p>如果要导出镜像到本地文件，可以使用 <code>docker save</code> 命令。</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">$ sudo docker images</span><br><span class="line">REPOSITORY          TAG                 IMAGE ID            CREATED             VIRTUAL SIZE</span><br><span class="line">ubuntu              14.04               c4ff7513909d        5 weeks ago         225.4 MB</span><br><span class="line">...</span><br><span class="line">$sudo docker save -o ubuntu_14.04.tar ubuntu:14.04</span><br></pre></td></tr></table></figure>

<h3 id="载入镜像"><a href="#载入镜像" class="headerlink" title="载入镜像"></a>载入镜像</h3><p>可以使用 <code>docker load</code> 从导出的本地文件中再导入到本地镜像库，例如</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">$ sudo docker load --input ubuntu_14.04.tar</span><br></pre></td></tr></table></figure>

<p>或</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">$ sudo docker load &lt; ubuntu_14.04.tar</span><br></pre></td></tr></table></figure>

<p>这将导入镜像以及其相关的元数据信息（包括标签等）。</p>
<h2 id="移除本地镜像"><a href="#移除本地镜像" class="headerlink" title="移除本地镜像"></a>移除本地镜像</h2><p>如果要移除本地的镜像，可以使用 <code>docker rmi</code> 命令。注意 <code>docker rm</code> 命令是移除容器。</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">$ sudo docker rmi training/sinatra</span><br><span class="line">Untagged: training/sinatra:latest</span><br><span class="line">Deleted: 5bc342fa0b91cabf65246837015197eecfa24b2213ed6a51a8974ae250fedd8d</span><br><span class="line">Deleted: ed0fffdcdae5eb2c3a55549857a8be7fc8bc4241fb19ad714364cbfd7a56b22f</span><br><span class="line">Deleted: 5c58979d73ae448df5af1d8142436d81116187a7633082650549c52c3a2418f0</span><br></pre></td></tr></table></figure>

<ul>
<li>注意：在删除镜像之前要先用 <code>docker rm</code> 删掉依赖于这个镜像的所有容器。</li>
</ul>
<h2 id="镜像的实现原理"><a href="#镜像的实现原理" class="headerlink" title="镜像的实现原理"></a>镜像的实现原理</h2><p>Docker 镜像是怎么实现增量的修改和维护的？ 每个镜像都由很多层次构成，Docker 使用 Union FS 将这些不同的层结合到一个镜像中去。</p>
<p>通常 Union FS 有两个用途, 一方面可以实现不借助 LVM、RAID 将多个 disk  挂到同一个目录下,另一个更常用的就是将一个只读的分支和一个可写的分支联合在一起，Live CD  正是基于此方法可以允许在镜像不变的基础上允许用户在其上进行一些写操作。 Docker 在 AUFS 上构建的容器也是利用了类似的原理。</p>
<h1 id="Docker容器"><a href="#Docker容器" class="headerlink" title="Docker容器"></a>Docker容器</h1><h2 id="启动容器"><a href="#启动容器" class="headerlink" title="启动容器"></a>启动容器</h2><p>启动容器有两种方式，一种是基于镜像新建一个容器并启动，另外一个是将在终止状态（stopped）的容器重新启动。</p>
<p>因为 Docker 的容器实在太轻量级了，很多时候用户都是随时删除和新创建容器。</p>
<h3 id="新建并启动"><a href="#新建并启动" class="headerlink" title="新建并启动"></a>新建并启动</h3><p>所需要的命令主要为 <code>docker run</code>。</p>
<p>例如，下面的命令输出一个 “Hello World”，之后终止容器。</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">$ sudo docker run ubuntu:14.04 /bin/echo &#x27;Hello world&#x27;</span><br><span class="line">Hello world</span><br><span class="line"></span><br><span class="line">docker run -d -p 80:80 docker/getting-started</span><br></pre></td></tr></table></figure>

<p>这跟在本地直接执行 <code>/bin/echo &#39;hello world&#39;</code> 几乎感觉不出任何区别。</p>
<p>下面的命令则启动一个 bash 终端，允许用户进行交互。</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">$ sudo docker run -t -i ubuntu:14.04 /bin/bash</span><br><span class="line">root@af8bae53bdd3:/#</span><br></pre></td></tr></table></figure>

<p>其中，<code>-t</code> 选项让Docker分配一个伪终端（pseudo-tty）并绑定到容器的标准输入上， <code>-i</code> 则让容器的标准输入保持打开。</p>
<p>在交互模式下，用户可以通过所创建的终端来输入命令，例如</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">root@af8bae53bdd3:/# pwd</span><br><span class="line">/</span><br><span class="line">root@af8bae53bdd3:/# ls</span><br><span class="line">bin boot dev etc home lib lib64 media mnt opt proc root run sbin srv sys tmp usr var</span><br></pre></td></tr></table></figure>

<p>当利用 <code>docker run</code> 来创建容器时，Docker 在后台运行的标准操作包括：</p>
<ul>
<li>检查本地是否存在指定的镜像，不存在就从公有仓库下载</li>
<li>利用镜像创建并启动一个容器</li>
<li>分配一个文件系统，并在只读的镜像层外面挂载一层可读写层</li>
<li>从宿主主机配置的网桥接口中桥接一个虚拟接口到容器中去</li>
<li>从地址池配置一个 ip 地址给容器</li>
<li>执行用户指定的应用程序</li>
<li>执行完毕后容器被终止</li>
</ul>
<h3 id="启动已终止容器"><a href="#启动已终止容器" class="headerlink" title="启动已终止容器"></a>启动已终止容器</h3><p>可以利用 <code>docker start</code> 命令，直接将一个已经终止的容器启动运行。</p>
<p>容器的核心为所执行的应用程序，所需要的资源都是应用程序运行所必需的。除此之外，并没有其它的资源。可以在伪终端中利用 <code>ps</code> 或 <code>top</code> 来查看进程信息。</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">root@ba267838cc1b:/# ps</span><br><span class="line">  PID TTY          TIME CMD</span><br><span class="line">    1 ?        00:00:00 bash</span><br><span class="line">   11 ?        00:00:00 ps</span><br></pre></td></tr></table></figure>

<p>可见，容器中仅运行了指定的 bash 应用。这种特点使得 Docker 对资源的利用率极高，是货真价实的轻量级虚拟化。</p>
<h2 id="守护态运行"><a href="#守护态运行" class="headerlink" title="守护态运行"></a>守护态运行</h2><p>更多的时候，需要让 Docker 容器在后台以守护态（Daemonized）形式运行。此时，可以通过添加 <code>-d</code> 参数来实现。</p>
<p>例如下面的命令会在后台运行容器。</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">$ sudo docker run -d ubuntu:14.04 /bin/sh -c &quot;while true; do echo hello world; sleep 1; done&quot;</span><br><span class="line">1e5535038e285177d5214659a068137486f96ee5c2e85a4ac52dc83f2ebe4147</span><br></pre></td></tr></table></figure>

<p>容器启动后会返回一个唯一的 id，也可以通过 <code>docker ps</code> 命令来查看容器信息。</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">$ sudo docker ps</span><br><span class="line">CONTAINER ID  IMAGE         COMMAND               CREATED        STATUS       PORTS NAMES</span><br><span class="line">1e5535038e28  ubuntu:14.04  /bin/sh -c &#x27;while tr  2 minutes ago  Up 1 minute        insane_babbage</span><br></pre></td></tr></table></figure>

<p>要获取容器的输出信息，可以通过 <code>docker logs</code> 命令。</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">$ sudo docker logs insane_babbage</span><br><span class="line">hello world</span><br><span class="line">hello world</span><br><span class="line">hello world</span><br><span class="line">. . .</span><br></pre></td></tr></table></figure>

<h2 id="终止容器"><a href="#终止容器" class="headerlink" title="终止容器"></a>终止容器</h2><p>可以使用 <code>docker stop</code> 来终止一个运行中的容器。</p>
<p>此外，当Docker容器中指定的应用终结时，容器也自动终止。 例如对于上一章节中只启动了一个终端的容器，用户通过 <code>exit</code> 命令或 <code>Ctrl+d</code> 来退出终端时，所创建的容器立刻终止。</p>
<p>终止状态的容器可以用 <code>docker ps -a</code> 命令看到。例如</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">sudo docker ps -a</span><br><span class="line">CONTAINER ID        IMAGE                    COMMAND                CREATED             STATUS                          PORTS               NAMES</span><br><span class="line">ba267838cc1b        ubuntu:14.04             &quot;/bin/bash&quot;            30 minutes ago      Exited (0) About a minute ago                       trusting_newton</span><br><span class="line">98e5efa7d997        training/webapp:latest   &quot;python app.py&quot;        About an hour ago   Exited (0) 34 minutes ago                           backstabbing_pike</span><br></pre></td></tr></table></figure>

<p>处于终止状态的容器，可以通过 <code>docker start</code> 命令来重新启动。</p>
<p>此外，<code>docker restart</code> 命令会将一个运行态的容器终止，然后再重新启动它。</p>
<h2 id="进入容器"><a href="#进入容器" class="headerlink" title="进入容器"></a>进入容器</h2><p>在使用 <code>-d</code> 参数时，容器启动后会进入后台。 某些时候需要进入容器进行操作，有很多种方法，包括使用<code>docker attach</code> 命令或 <code>nsenter</code> 工具等。</p>
<h3 id="attach-命令"><a href="#attach-命令" class="headerlink" title="attach 命令"></a>attach 命令</h3><p><code>docker attach</code> 是Docker自带的命令。下面示例如何使用该命令。</p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line">$ sudo docker run -idt ubuntu</span><br><span class="line">243c32535da7d142fb0e6df616a3c3ada0b8ab417937c853a9e1c251f499f550</span><br><span class="line">$ sudo docker ps</span><br><span class="line">CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS               NAMES</span><br><span class="line">243c32535da7        ubuntu:latest       <span class="string">&quot;/bin/bash&quot;</span>         18 seconds ago      Up 17 seconds                           nostalgic_hypatia</span><br><span class="line"><span class="variable">$sudo</span> docker attach nostalgic_hypatia</span><br><span class="line">root@243c32535da7:/<span class="comment">#</span></span><br></pre></td></tr></table></figure>

<p>但是使用 <code>attach</code> 命令有时候并不方便。当多个窗口同时 attach 到同一个容器的时候，所有窗口都会同步显示。当某个窗口因命令阻塞时,其他窗口也无法执行操作了。</p>
<h3 id="nsenter-命令"><a href="#nsenter-命令" class="headerlink" title="nsenter 命令"></a>nsenter 命令</h3><h4 id="安装"><a href="#安装" class="headerlink" title="安装"></a>安装</h4><p><code>nsenter</code> 工具在 util-linux 包2.23版本后包含。 如果系统中 util-linux 包没有该命令，可以按照下面的方法从源码安装。</p>
<figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta prompt_">$ </span><span class="language-bash"><span class="built_in">cd</span> /tmp; curl https://www.kernel.org/pub/linux/utils/util-linux/v2.24/util-linux-2.24.tar.gz | tar -zxf-; <span class="built_in">cd</span> util-linux-2.24;</span></span><br><span class="line"><span class="meta prompt_">$ </span><span class="language-bash">./configure --without-ncurses</span></span><br><span class="line"><span class="meta prompt_">$ </span><span class="language-bash">make nsenter &amp;&amp; sudo <span class="built_in">cp</span> nsenter /usr/local/bin</span></span><br></pre></td></tr></table></figure>

<h4 id="使用"><a href="#使用" class="headerlink" title="使用"></a>使用</h4><p><code>nsenter</code> 可以访问另一个进程的名字空间。nsenter 要正常工作需要有 root 权限。 很不幸，Ubuntu 14.04 仍然使用的是 util-linux 2.20。安装最新版本的 util-linux（2.24）版，请按照以下步骤：</p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">$ wget https://www.kernel.org/pub/linux/utils/util-linux/v2.24/util-linux-2.24.tar.gz; tar xzvf util-linux-2.24.tar.gz</span><br><span class="line">$ <span class="built_in">cd</span> util-linux-2.24</span><br><span class="line">$ ./configure --without-ncurses &amp;&amp; make nsenter</span><br><span class="line">$ sudo <span class="built_in">cp</span> nsenter /usr/local/bin</span><br></pre></td></tr></table></figure>

<p>为了连接到容器，你还需要找到容器的第一个进程的 PID，可以通过下面的命令获取。</p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">PID=$(docker inspect --format <span class="string">&quot;&#123;&#123; .State.Pid &#125;&#125;&quot;</span> &lt;container&gt;)</span><br></pre></td></tr></table></figure>

<p>通过这个 PID，就可以连接到这个容器：</p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">$ nsenter --target <span class="variable">$PID</span> --mount --uts --ipc --net --pid</span><br></pre></td></tr></table></figure>

<p>下面给出一个完整的例子。</p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line">$ sudo docker run -idt ubuntu</span><br><span class="line">243c32535da7d142fb0e6df616a3c3ada0b8ab417937c853a9e1c251f499f550</span><br><span class="line">$ sudo docker ps</span><br><span class="line">CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS               NAMES</span><br><span class="line">243c32535da7        ubuntu:latest       <span class="string">&quot;/bin/bash&quot;</span>         18 seconds ago      Up 17 seconds                           nostalgic_hypatia</span><br><span class="line">$ PID=$(docker-pid 243c32535da7)</span><br><span class="line">10981</span><br><span class="line">$ sudo nsenter --target 10981 --mount --uts --ipc --net --pid</span><br><span class="line">root@243c32535da7:/<span class="comment">#</span></span><br></pre></td></tr></table></figure>

<p>更简单的，建议大家下载 .bashrc_docker，并将内容放到 .bashrc 中。</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">$ wget -P ~ https://github.com/yeasy/docker_practice/raw/master/_local/.bashrc_docker;</span><br><span class="line">$ echo &quot;[ -f ~/.bashrc_docker ] &amp;&amp; . ~/.bashrc_docker&quot; &gt;&gt; ~/.bashrc; source ~/.bashrc</span><br></pre></td></tr></table></figure>

<p>这个文件中定义了很多方便使用 Docker 的命令，例如 <code>docker-pid</code> 可以获取某个容器的 PID；而 <code>docker-enter</code> 可以进入容器或直接在容器内执行命令。</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">$ echo $(docker-pid &lt;container&gt;)</span><br><span class="line">$ docker-enter &lt;container&gt; ls</span><br></pre></td></tr></table></figure>

<h2 id="导出和导入容器"><a href="#导出和导入容器" class="headerlink" title="导出和导入容器"></a>导出和导入容器</h2><h3 id="导出容器"><a href="#导出容器" class="headerlink" title="导出容器"></a>导出容器</h3><p>如果要导出本地某个容器，可以使用 <code>docker export</code> 命令。</p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">$ sudo docker ps -a</span><br><span class="line">CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS                    PORTS               NAMES</span><br><span class="line">7691a814370e        ubuntu:14.04        <span class="string">&quot;/bin/bash&quot;</span>         36 hours ago        Exited (0) 21 hours ago                       <span class="built_in">test</span></span><br><span class="line">$ sudo docker <span class="built_in">export</span> 7691a814370e &gt; ubuntu.tar</span><br></pre></td></tr></table></figure>

<p>这样将导出容器快照到本地文件。</p>
<h3 id="导入容器快照"><a href="#导入容器快照" class="headerlink" title="导入容器快照"></a>导入容器快照</h3><p>可以使用 <code>docker import</code> 从容器快照文件中再导入为镜像，例如</p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">$ <span class="built_in">cat</span> ubuntu.tar | sudo docker import - <span class="built_in">test</span>/ubuntu:v1.0</span><br><span class="line">$ sudo docker images</span><br><span class="line">REPOSITORY          TAG                 IMAGE ID            CREATED              VIRTUAL SIZE</span><br><span class="line"><span class="built_in">test</span>/ubuntu         v1.0                9d37a6082e97        About a minute ago   171.3 MB</span><br></pre></td></tr></table></figure>

<p>此外，也可以通过指定 URL 或者某个目录来导入，例如</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">$sudo docker import http://example.com/exampleimage.tgz example/imagerepo</span><br></pre></td></tr></table></figure>

<p>*注：用户既可以使用 <code>docker load</code> 来导入镜像存储文件到本地镜像库，也可以使用 <code>docker import</code> 来导入一个容器快照到本地镜像库。这两者的区别在于容器快照文件将丢弃所有的历史记录和元数据信息（即仅保存容器当时的快照状态），而镜像存储文件将保存完整记录，体积也要大。此外，从容器快照文件导入时可以重新指定标签等元数据信息。</p>
<h2 id="删除容器"><a href="#删除容器" class="headerlink" title="删除容器"></a>删除容器</h2><p>可以使用 <code>docker rm</code> 来删除一个处于终止状态的容器。 例如</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">$sudo docker rm  trusting_newton</span><br><span class="line">trusting_newton</span><br></pre></td></tr></table></figure>

<p>如果要删除一个运行中的容器，可以添加 <code>-f</code> 参数。Docker 会发送 <code>SIGKILL</code> 信号给容器。</p>
<h1 id="数据卷"><a href="#数据卷" class="headerlink" title="数据卷"></a>数据卷</h1><h2 id="数据卷volumes"><a href="#数据卷volumes" class="headerlink" title="数据卷volumes"></a>数据卷volumes</h2><p>数据卷是一个可供一个或多个容器使用的特殊目录，它绕过 UFS，可以提供很多有用的特性：</p>
<ul>
<li>数据卷可以在容器之间共享和重用</li>
<li>对数据卷的修改会立马生效</li>
<li>对数据卷的更新，不会影响镜像</li>
<li>卷会一直存在，直到没有容器使用</li>
</ul>
<p>*数据卷的使用，类似于 Linux 下对目录或文件进行 mount。</p>
<h3 id="创建一个数据卷"><a href="#创建一个数据卷" class="headerlink" title="创建一个数据卷"></a>创建一个数据卷</h3><p>在用 <code>docker run</code> 命令的时候，使用 <code>-v</code> 标记来创建一个数据卷并挂载到容器里。在一次 run 中多次使用可以挂载多个数据卷。</p>
<p>下面创建一个 web 容器，并加载一个数据卷到容器的 <code>/webapp</code> 目录。</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">$ sudo docker run -d -P --name web -v /webapp training/webapp python app.py</span><br></pre></td></tr></table></figure>

<p>*注意：也可以在 Dockerfile 中使用 <code>VOLUME</code> 来添加一个或者多个新的卷到由该镜像创建的任意容器。</p>
<h3 id="挂载一个主机目录作为数据卷"><a href="#挂载一个主机目录作为数据卷" class="headerlink" title="挂载一个主机目录作为数据卷"></a>挂载一个主机目录作为数据卷</h3><p>使用 <code>-v</code> 标记也可以指定挂载一个本地主机的目录到容器中去。</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">$ sudo docker run -d -P --name web -v /src/webapp:/opt/webapp training/webapp python app.py</span><br></pre></td></tr></table></figure>

<p>上面的命令加载主机的 <code>/src/webapp</code> 目录到容器的 <code>/opt/webapp</code> 目录。这个功能在进行测试的时候十分方便，比如用户可以放置一些程序到本地目录中，来查看容器是否正常工作。本地目录的路径必须是绝对路径，如果目录不存在 Docker 会自动为你创建它。</p>
<p>*注意：Dockerfile 中不支持这种用法，这是因为 Dockerfile 是为了移植和分享用的。然而，不同操作系统的路径格式不一样，所以目前还不能支持。</p>
<p>Docker 挂载数据卷的默认权限是读写，用户也可以通过 <code>:ro</code> 指定为只读。</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">$ sudo docker run -d -P --name web -v /src/webapp:/opt/webapp:ro</span><br><span class="line">training/webapp python app.py</span><br></pre></td></tr></table></figure>

<p>加了 <code>:ro</code> 之后，就挂载为只读了。</p>
<h3 id="挂载一个本地主机文件作为数据卷"><a href="#挂载一个本地主机文件作为数据卷" class="headerlink" title="挂载一个本地主机文件作为数据卷"></a>挂载一个本地主机文件作为数据卷</h3><p><code>-v</code> 标记也可以从主机挂载单个文件到容器中</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">$ sudo docker run --rm -it -v ~/.bash_history:/.bash_history ubuntu /bin/bash</span><br></pre></td></tr></table></figure>

<p>这样就可以记录在容器输入过的命令了。</p>
<p>*注意：如果直接挂载一个文件，很多文件编辑工具，包括 <code>vi</code> 或者 <code>sed --in-place</code>，可能会造成文件 inode 的改变，从 Docker 1.1 .0起，这会导致报错误信息。所以最简单的办法就直接挂载文件的父目录。</p>
<h2 id="数据卷容器"><a href="#数据卷容器" class="headerlink" title="数据卷容器"></a>数据卷容器</h2><p>如果你有一些持续更新的数据需要在容器之间共享，最好创建数据卷容器。</p>
<p>数据卷容器，其实就是一个正常的容器，专门用来提供数据卷供其它容器挂载的。</p>
<p>首先，创建一个命名的数据卷容器 dbdata：</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">$ sudo docker run -d -v /dbdata --name dbdata training/postgres echo Data-only container for postgres</span><br></pre></td></tr></table></figure>

<p>然后，在其他容器中使用 <code>--volumes-from</code> 来挂载 dbdata 容器中的数据卷。</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">$ sudo docker run -d --volumes-from dbdata --name db1 training/postgres</span><br><span class="line">$ sudo docker run -d --volumes-from dbdata --name db2 training/postgres</span><br></pre></td></tr></table></figure>

<p>还可以使用多个 <code>--volumes-from</code> 参数来从多个容器挂载多个数据卷。 也可以从其他已经挂载了数据卷的容器来挂载数据卷。</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">$ sudo docker run -d --name db3 --volumes-from db1 training/postgres</span><br></pre></td></tr></table></figure>

<p>*注意：使用 <code>--volumes-from</code> 参数所挂载数据卷的容器自己并不需要保持在运行状态。</p>
<p>如果删除了挂载的容器（包括 dbdata、db1 和 db2），数据卷并不会被自动删除。如果要删除一个数据卷，必须在删除最后一个还挂载着它的容器时使用 <code>docker rm -v</code> 命令来指定同时删除关联的容器。 这可以让用户在容器之间升级和移动数据卷。具体的操作将在下一节中进行讲解。</p>
<h2 id="利用数据卷容器来备份、恢复、迁移数据卷"><a href="#利用数据卷容器来备份、恢复、迁移数据卷" class="headerlink" title="利用数据卷容器来备份、恢复、迁移数据卷"></a>利用数据卷容器来备份、恢复、迁移数据卷</h2><p>可以利用数据卷对其中的数据进行进行备份、恢复和迁移。</p>
<h3 id="备份"><a href="#备份" class="headerlink" title="备份"></a>备份</h3><p>首先使用 <code>--volumes-from</code> 标记来创建一个加载 dbdata 容器卷的容器，并从本地主机挂载当前到容器的 /backup 目录。命令如下：</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">$ sudo docker run --volumes-from dbdata -v $(pwd):/backup ubuntu tar cvf /backup/backup.tar /dbdata</span><br></pre></td></tr></table></figure>

<p>容器启动后，使用了 <code>tar</code> 命令来将 dbdata 卷备份为本地的 <code>/backup/backup.tar</code>。</p>
<h3 id="恢复"><a href="#恢复" class="headerlink" title="恢复"></a>恢复</h3><p>如果要恢复数据到一个容器，首先创建一个带有数据卷的容器 dbdata2。</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">$ sudo docker run -v /dbdata --name dbdata2 ubuntu /bin/bash</span><br></pre></td></tr></table></figure>

<p>然后创建另一个容器，挂载 dbdata2 的容器，并使用 <code>untar</code> 解压备份文件到挂载的容器卷中。</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">$ sudo docker run --volumes-from dbdata2 -v $(pwd):/backup busybox tar xvf</span><br><span class="line">/backup/backup.tar</span><br></pre></td></tr></table></figure>

<h1 id="安装docker"><a href="#安装docker" class="headerlink" title="安装docker"></a>安装docker</h1><blockquote>
<p>环境准备</p>
</blockquote>
<ol>
<li><p>需要一点点的liunx基础</p>
</li>
<li><p>centos7</p>
</li>
<li><p>使用xshell连接远程服务器进行操作</p>
</li>
<li><p>卸载旧版本 </p>
</li>
</ol>
<blockquote>
<p>yum remove docker</p>
</blockquote>
<ol start="2">
<li>需要的安装包 </li>
</ol>
<blockquote>
<p>yum install -y yum-utils</p>
</blockquote>
<ol start="3">
<li>设置镜像的仓库</li>
</ol>
<blockquote>
<p>yum-config-manager –add-repo <a target="_blank" rel="noopener" href="http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo">http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo</a></p>
</blockquote>
<p>更新索引</p>
<blockquote>
<p>yum makecache fast</p>
</blockquote>
<ol start="4">
<li>安装docker社区版</li>
</ol>
<blockquote>
<p>yum install docker-ce docker-ce-cli containerd.io</p>
<p>//其他方式 </p>
<p>yum clean all yum makecache fastyum -y install docker-ce</p>
</blockquote>
<ol start="5">
<li>启动docker</li>
</ol>
<blockquote>
<p>systemctl start docker</p>
</blockquote>
<ol start="6">
<li>测试</li>
</ol>
<blockquote>
<p>docker version</p>
<p>docker run hello-world</p>
</blockquote>
<ol start="7">
<li>查看镜像在不在</li>
</ol>
<blockquote>
<p>docker images</p>
</blockquote>
<ol start="8">
<li>卸载docker</li>
</ol>
<blockquote>
<p>yum remove docker-ce docker-ce-cli containerd.io</p>
<p>yum rm -rf /var/lib/docker</p>
</blockquote>
<p>阿里云镜像加速</p>
<blockquote>
<p>登录阿里云 找到容器服务</p>
<p>找到镜像加速地址</p>
<p>配置使用</p>
</blockquote>
<h1 id="Docker的常用命令"><a href="#Docker的常用命令" class="headerlink" title="Docker的常用命令"></a>Docker的常用命令</h1><p>帮助命令 </p>
<figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">docker version 		# 显示cker版本信息</span><br><span class="line">docker info			#显示docker 的系统信息 包括镜像和容器的数量</span><br><span class="line">docker 命令 --help  	#帮助命令</span><br></pre></td></tr></table></figure>

<h2 id="镜像命令"><a href="#镜像命令" class="headerlink" title="镜像命令"></a>镜像命令</h2><p><strong>docker images</strong>      </p>
<figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">[root@localhost ~]# docker images</span><br><span class="line">REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE</span><br><span class="line">hello-world         latest              bf756fb1ae65        5 months ago        13.3kB</span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">可选</span></span><br><span class="line">-a --all  #列出所有镜像的详细信息</span><br><span class="line">-q --quiet  #列出镜像的id</span><br></pre></td></tr></table></figure>

<p><strong>docker search 搜索镜像</strong></p>
<figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta prompt_">#</span><span class="language-bash">可选项目</span></span><br><span class="line">-f --filter=STARS=3000 #搜索出镜像大于3000的</span><br></pre></td></tr></table></figure>

<p><strong>docker pull 下载镜像</strong></p>
<figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br></pre></td><td class="code"><pre><span class="line">[root@localhost ~]# docker pull mysql</span><br><span class="line"></span><br><span class="line">Using default tag: latest  #如果不写 默认 latest</span><br><span class="line">latest: Pulling from library/mysql</span><br><span class="line">8559a31e96f4: Pull complete   # 分层下载 docker images的核心 联合文件系统</span><br><span class="line">d51ce1c2e575: Pull complete </span><br><span class="line">c2344adc4858: Pull complete </span><br><span class="line">fcf3ceff18fc: Pull complete </span><br><span class="line">16da0c38dc5b: Pull complete </span><br><span class="line">b905d1797e97: Pull complete </span><br><span class="line">4b50d1c6b05c: Pull complete </span><br><span class="line">c75914a65ca2: Pull complete </span><br><span class="line">1ae8042bdd09: Downloading [=&gt;                                                 ]  3.734MB/111.5MB</span><br><span class="line">453ac13c00a3: Download complete </span><br><span class="line">9e680cd72f08: Download complete </span><br><span class="line">a6b5dc864b6c: Download complete </span><br><span class="line">Digest: sha256:8b7b328a7ff6de46ef96bcf83af048cb00a1c86282bfca0cb119c84568b4caf6</span><br><span class="line">Status: Downloaded newer image for mysql:latest</span><br><span class="line">docker.io/library/mysql:latest</span><br></pre></td></tr></table></figure>

<p><strong>docker rmi 删除镜像</strong> $(docker images -aq) 全部删除</p>
<figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">docker rmi  -f 镜像 ID #删除指定内容</span><br><span class="line">docker rmi  -f 镜像 ID  $(docker images -aq) 全部删除</span><br></pre></td></tr></table></figure>

<h2 id="容器命令"><a href="#容器命令" class="headerlink" title="容器命令"></a>容器命令</h2><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br></pre></td><td class="code"><pre><span class="line">docker run [可选参数] image</span><br><span class="line"><span class="meta prompt_"></span></span><br><span class="line"><span class="meta prompt_">#</span><span class="language-bash">参数说明</span></span><br><span class="line">--name =&quot;Name&quot; 容器名字 tomcat 01  用来区分容器</span><br><span class="line"></span><br><span class="line">-d         			后台运行</span><br><span class="line">-it  			   使用交互方式 运行 进入容器 查看内容</span><br><span class="line">-p 				指定容器的端口 -p 8080:8080</span><br><span class="line">-P			       随机指定端口</span><br><span class="line">-p 				主机端口:容器端口</span><br><span class="line">-p 				容器端口</span><br><span class="line"><span class="meta prompt_">		</span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">测试 启动并进入 centos 基础版本</span> </span><br><span class="line">[root@localhost ~]# docker run -it centos /bin/bash</span><br><span class="line">[root@fd52fe0bc9f8 /]# </span><br><span class="line"><span class="meta prompt_"></span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">退回到主机</span></span><br><span class="line">exit</span><br><span class="line"></span><br><span class="line">docker ps      当前正在运行的容器 </span><br><span class="line">docker ps -a   曾经运行过的</span><br><span class="line">-n= ?  显示最近创建的容器 </span><br><span class="line">-q     只显示容器的编号 </span><br><span class="line">-aq  显示所有容器 的编号</span><br><span class="line"><span class="meta prompt_"></span></span><br><span class="line"><span class="meta prompt_"></span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">ctrl+p+q  容器不停止 退出</span></span><br><span class="line">删除容器</span><br><span class="line">docker rm  容器id						不能删除正在运行的容器</span><br><span class="line">docker rm -f $(docker ps -aq) 			删除所有容器</span><br><span class="line">docker ps -a -q|xargs docker rm</span><br></pre></td></tr></table></figure>

<p><strong>启动和停止 容器的操作</strong></p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">docker start 容器id</span><br><span class="line">docker restart 容器id</span><br><span class="line">docker stop 容器id </span><br><span class="line">docker kill 容器id    # 强制停止</span><br></pre></td></tr></table></figure>

<h2 id="常用其他命令"><a href="#常用其他命令" class="headerlink" title="常用其他命令"></a>常用其他命令</h2><p><strong>后台启动</strong></p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"># 命令docker run -d 镜像名</span><br><span class="line">docker run -d centos</span><br><span class="line">常见的坑 docker 容器使用后台运行 就必须要有一个前台进程</span><br></pre></td></tr></table></figure>

<p><strong>查看日志命令</strong></p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">docker logs  -tf --tail number 容器</span><br></pre></td></tr></table></figure>

<p><strong>查看容器中的进程信息</strong></p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">docker top 容器id</span><br></pre></td></tr></table></figure>

<p><strong>查看镜像的元数据</strong></p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">docker inspect 容器id</span><br></pre></td></tr></table></figure>

<p><strong>进入当前正在运行的容器</strong></p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">通常容器都是使用后台 </span><br><span class="line">#方式一</span><br><span class="line">docker exec -it 容器id bashShell</span><br><span class="line">#方式二</span><br><span class="line">docker attach 容器ID</span><br></pre></td></tr></table></figure>

<p>方式一  进入之后开启一个新的终端<br>方式二  进入容器正在执行的终端</p>
<p><strong>从容器内拷贝文件到主机上</strong></p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line">docker cp 容器id:容器内路径 目的主机路径</span><br><span class="line">attach 进入 容器</span><br><span class="line"></span><br><span class="line">#touch test.java 新建文件</span><br><span class="line">docker cp  id:/home/test.java /home  拷贝</span><br><span class="line"></span><br><span class="line">未来使用-v卷的技术 可以实现自动</span><br><span class="line">[root@localhost ~]# curl localhost:8888</span><br><span class="line">端口 暴露</span><br></pre></td></tr></table></figure>

<p>以后要部署项目 如果每次进入容器 十分麻烦 webapps 在外部放置项目 就自动同步到内部</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line">#es 暴露的端口很多</span><br><span class="line">#es 十分耗内存</span><br><span class="line">#es 的数据一般需要放置到安全目录</span><br><span class="line"></span><br><span class="line">docker run -d --name elasticsearch --net somenetwork -p 9200:9200 -p 9300:9300 -e &quot;discovery.type=single-node&quot; elasticsearch:tag</span><br><span class="line"></span><br><span class="line"></span><br><span class="line">--net网络配置</span><br></pre></td></tr></table></figure>

<p>docker stats 查看cpu的状态 </p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">增加内存限制 修改配置参数 -e 环境配置参数</span><br><span class="line">docker run -d --name elasticsearch --net somenetwork -p 9200:9200 -p 9300:9300 -e &quot;discovery.type=single-node&quot;  -e ES_JAVA_OPTS=&quot;-Xms64m -Xmx512m&quot; elasticsearch:7.7.1</span><br></pre></td></tr></table></figure>

<h2 id="相关自启设置"><a href="#相关自启设置" class="headerlink" title="相关自启设置"></a>相关自启设置</h2><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># linux自动启动docker</span></span><br><span class="line">systemctl <span class="built_in">enable</span> docker.service</span><br><span class="line"></span><br><span class="line"><span class="comment"># docker容器自动启动设置 查看id</span></span><br><span class="line">docker ps -a</span><br><span class="line">docker restart &lt;imageid&gt;</span><br><span class="line"></span><br><span class="line">docker run --restart=always</span><br><span class="line"><span class="comment"># 创建时：总是auto restart容器。</span></span><br><span class="line">docker run -d --restart=always xxx </span><br><span class="line"><span class="comment"># 　10次重启</span></span><br><span class="line">docker run -d --restart=on-failure:10 xxx</span><br><span class="line"><span class="comment"># 如果已经启动了则可以使用如下命令：</span></span><br><span class="line">docker update --restart=always &lt;CONTAINER ID&gt;</span><br><span class="line"></span><br></pre></td></tr></table></figure>



<blockquote>
<p>Manjaro基于archlinux的系统 自用备份 可无视</p>
</blockquote>
<h1 id="Manjaro安装Docker-自用备份"><a href="#Manjaro安装Docker-自用备份" class="headerlink" title="Manjaro安装Docker(自用备份)"></a>Manjaro安装Docker(自用备份)</h1><h2 id="基本安装"><a href="#基本安装" class="headerlink" title="基本安装#"></a>基本安装<a target="_blank" rel="noopener" href="https://www.cnblogs.com/imzhizi/p/10718310.html#662275148">#</a></h2><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line">Copy<span class="comment"># Pacman 安装 Docker</span></span><br><span class="line">sudo pacman -S docker</span><br><span class="line"><span class="comment"># 启动docker服务</span></span><br><span class="line">sudo systemctl start docker </span><br><span class="line"></span><br><span class="line"><span class="comment"># 查看docker服务的状态</span></span><br><span class="line">sudo systemctl status docker</span><br><span class="line"></span><br><span class="line"><span class="comment"># 设置docker开机启动服务</span></span><br><span class="line">sudo systemctl <span class="built_in">enable</span> docker</span><br></pre></td></tr></table></figure>

<h2 id="干掉讨厌的-sudo"><a href="#干掉讨厌的-sudo" class="headerlink" title="干掉讨厌的 sudo#"></a>干掉讨厌的 sudo<a target="_blank" rel="noopener" href="https://www.cnblogs.com/imzhizi/p/10718310.html#1764793316">#</a></h2><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line">Copy<span class="comment"># 如果还没有 docker group 就添加一个</span></span><br><span class="line">sudo groupadd docker</span><br><span class="line"><span class="comment"># 将自己的登录名($&#123;USER&#125; )加入该 group 内。然后退出并重新登录就生效啦</span></span><br><span class="line">sudo gpasswd -a <span class="variable">$&#123;USER&#125;</span> docker</span><br><span class="line"><span class="comment"># 重启 docker 服务</span></span><br><span class="line">sudo systemctl restart docker</span><br><span class="line"><span class="comment"># 切换当前会话到新 group 或者重启 X 会话</span></span><br><span class="line"><span class="comment"># 注意，这一步是必须的，否则因为 groups 命令获取到的是缓存的组信息，刚添加的组信息未能生效，所以 docker images 执行时同样有错。</span></span><br><span class="line">newgrp - docker</span><br><span class="line">OR</span><br><span class="line">pkill X</span><br></pre></td></tr></table></figure>



<h1 id="Docker-安装mqsql"><a href="#Docker-安装mqsql" class="headerlink" title="Docker 安装mqsql"></a>Docker 安装mqsql</h1><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">docker run --privileged=true</span><br><span class="line">-p 3306:3306 --name mysql -v //Users/xieyingtao/文档/项目/xytmall-docker/mysql/log:/var/log/mysql -v /Users/xieyingtao/文档/项目/xytmall-docker/mysql/data:/var/lib/mysql -v /Users/xieyingtao/文档/项目/xytmall-docker/mysql/conf:/etc/mysql -e MYSQL_ROOT_PASSWORD=root -d mysql</span><br></pre></td></tr></table></figure>

<ul>
<li>-p: 将容器的3306的端口映射到主机的3306</li>
<li>-v </li>
</ul>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br></pre></td><td class="code"><pre><span class="line"> </span><br><span class="line">//根目录选择自身实际最大磁盘路径 一般为/home 或者定义/data </span><br><span class="line">vi /data/mysql/conf/my.cnf</span><br><span class="line"> </span><br><span class="line">//insert 插入以下内容</span><br><span class="line"> </span><br><span class="line">[mysqld]</span><br><span class="line"> </span><br><span class="line">#服务端口号 默认3306</span><br><span class="line">port=3306</span><br><span class="line">user=mysql</span><br><span class="line">#mysql数据文件所在位置</span><br><span class="line">datadir=/var/lib/mysql</span><br><span class="line"> </span><br><span class="line">#pid</span><br><span class="line">pid-file=/var/run/mysqld/mysqld.pid</span><br><span class="line">socket=/var/run/mysqld/mysqld.sock</span><br><span class="line">default-time-zone = &#x27;+8:00&#x27;</span><br><span class="line"> </span><br><span class="line">sql_mode=STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION</span><br><span class="line"># 允许访问的IP网段</span><br><span class="line">bind-address=0.0.0.0</span><br><span class="line"> </span><br><span class="line">#只能用IP地址检查客户端的登录，不用主机名</span><br><span class="line">skip_name_resolve=1</span><br><span class="line"> </span><br><span class="line">#事务隔离级别，默认为可重复读，mysql默认可重复读级别（此级别下可能参数很多间隙锁，影响性能）</span><br><span class="line">transaction_isolation=READ-COMMITTED</span><br><span class="line"> </span><br><span class="line"> </span><br><span class="line">#是否对sql语句大小写敏感，1表示不敏感</span><br><span class="line">lower_case_table_names=1</span><br><span class="line"> </span><br><span class="line">#最大连接数</span><br><span class="line">max_connections=400</span><br><span class="line"> </span><br><span class="line">#最大错误连接数</span><br><span class="line">max_connect_errors=1000</span><br><span class="line"> </span><br><span class="line">#TIMESTAMP如果没有显示声明NOT NULL，允许NULL值</span><br><span class="line">explicit_defaults_for_timestamp=true</span><br><span class="line"> </span><br><span class="line">#SQL数据包发送的大小，如果有BLOB对象建议修改成1G</span><br><span class="line">max_allowed_packet=1G</span><br><span class="line"> </span><br><span class="line">#数据库错误日志文件</span><br><span class="line">log-error=/var/log/mysqld.log</span><br></pre></td></tr></table></figure>



<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">docker run --privileged=true -p 3306:3306 -m 1g --name mysql -v /data/mysql/conf:/etc/mysql/conf.d -v /data/mysql/logs:/var/log/mysql -v /data/mysql/data:/var/lib/mysql -e MYSQL_ROOT_PASSWORD=root123 -d mysql:8.0.30</span><br></pre></td></tr></table></figure>

<p>开启远程连接权限</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br></pre></td><td class="code"><pre><span class="line">使用Docker命令进去mysql中</span><br><span class="line"></span><br><span class="line">docker exec -it 容器名 /bin/bash</span><br><span class="line"> 登录mysql数据库</span><br><span class="line"></span><br><span class="line">mysql -u root -p</span><br><span class="line">远程连接授权</span><br><span class="line"></span><br><span class="line">GRANT ALL PRIVILEGES ON *.* TO &#x27;root&#x27;@&#x27;%&#x27; IDENTIFIED BY &#x27;root&#x27; WITH GRANT OPTION;</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"># 进入mysql容器</span><br><span class="line">docker exec -it mysql bash</span><br><span class="line"># -u后接账户 -p接密码</span><br><span class="line">mysql -uroot -p123456</span><br><span class="line"># 外网范围授权</span><br><span class="line">grant all privileges on *.* to root@&#x27;%&#x27; identified by &quot;password&quot;;</span><br><span class="line"># 刷新权限</span><br><span class="line">flush privileges;</span><br><span class="line"># 一定要更新密码，否则Navicat连接报1045错误</span><br><span class="line">alter user &#x27;root&#x27;@&#x27;%&#x27; identified with mysql_native_password by &#x27;123456&#x27;;</span><br><span class="line"># 刷新权限</span><br><span class="line"></span><br><span class="line"></span><br><span class="line">grant all privileges on *.*  to &#x27;root&#x27;@&#x27;%&#x27; </span><br><span class="line"></span><br><span class="line">ALTER USER &#x27;root&#x27;@&#x27;%&#x27; IDENTIFIED WITH mysql_native_password BY &#x27;root&#x27;</span><br><span class="line"></span><br><span class="line"></span><br></pre></td></tr></table></figure>



<p>资料参考:  <a target="_blank" rel="noopener" href="http://www.dockerinfo.net/document">http://www.dockerinfo.net/document</a> ;狂神说java</p>
</article><div class="tag_share"><div class="post-meta__tag-list"><a class="post-meta__tags" href="/tags/Docker/">Docker</a></div><div class="post_share"><div class="social-share" data-image="https://ytblogpic.oss-cn-guangzhou.aliyuncs.com/typorau=2532140561,3610048596&amp;fm=26&amp;gp=0.jpg" data-sites="wechat,weibo,qq"></div><link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/butterfly-extsrc/sharejs/dist/css/share.min.css" media="print" onload="this.media='all'"><script src="https://cdn.jsdelivr.net/npm/butterfly-extsrc/sharejs/dist/js/social-share.min.js" defer></script></div></div><div class="post-reward"><div class="reward-button"><i class="fas fa-qrcode"></i> 打赏</div><div class="reward-main"><ul class="reward-all"><li class="reward-item"><a href="https://s2.loli.net/2022/08/21/Ay5sujrkH1nLTwW.jpg" target="_blank"><img class="post-qr-code-img" src= "" data-lazy-src="https://s2.loli.net/2022/08/21/Ay5sujrkH1nLTwW.jpg" alt="Wechat"/></a><div class="post-qr-code-desc">Wechat</div></li></ul></div></div><nav class="pagination-post" id="pagination"><div class="prev-post pull-left"><a href="/posts/Infinity/"><img class="prev-cover" src= "" data-lazy-src="https://ytblogpic.oss-cn-guangzhou.aliyuncs.com/typoraLinux.jpg" onerror="onerror=null;src='/img/404.jpg'" alt="cover of previous post"><div class="pagination-info"><div class="label">上一篇</div><div class="prev_info">Linux基础命令+Vim</div></div></a></div><div class="next-post pull-right"><a href="/posts/e3ba8d56/"><img class="next-cover" src= "" data-lazy-src="https://ytblogpic.oss-cn-guangzhou.aliyuncs.com/typoratimg.jpeg" onerror="onerror=null;src='/img/404.jpg'" alt="cover of next post"><div class="pagination-info"><div class="label">下一篇</div><div class="next_info">MySQL高级(二)--性能分析和优化</div></div></a></div></nav><hr/><div id="post-comment"><div class="comment-head"><div class="comment-headline"><i class="fas fa-comments fa-fw"></i><span> 评论</span></div></div><div class="comment-wrap"><div><div id="twikoo-wrap"></div></div></div></div></div><div class="aside-content" id="aside-content"><div class="card-widget card-info"><div class="is-center"><div class="avatar-img"><img src= "" data-lazy-src="https://s2.loli.net/2022/08/20/hk9Zvq4YRsIcnrw.jpg" onerror="this.onerror=null;this.src='/img/friend_404.gif'" alt="avatar"/></div><div class="author-info__name">樱桃先生</div><div class="author-info__description">樱桃先生的博客小站</div></div><div class="card-info-data site-data is-center"><a href="/archives/"><div class="headline">文章</div><div class="length-num">78</div></a><a href="/tags/"><div class="headline">标签</div><div class="length-num">65</div></a><a href="/categories/"><div class="headline">分类</div><div class="length-num">21</div></a></div><a id="card-info-btn" target="_blank" rel="noopener" href="https://ytblogpic.oss-cn-guangzhou.aliyuncs.com/typoraWechat.jpeg"><i class="fab fa-weixin"></i><span>加为好友</span></a></div><div class="card-widget card-announcement"><div class="item-headline"><i class="fas fa-bullhorn fa-shake"></i><span>公告</span></div><div class="announcement_content">欢迎光临樱桃小窝🍒～评论系统日常崩溃，没有找到长期稳定好用的组件。</div></div><div class="sticky_layout"><div class="card-widget" id="card-toc"><div class="item-headline"><i class="fas fa-stream"></i><span>目录</span><span class="toc-percentage"></span></div><div class="toc-content"><ol class="toc"><li class="toc-item toc-level-1"><a class="toc-link" href="#Docker"><span class="toc-number">1.</span> <span class="toc-text">Docker</span></a><ol class="toc-child"><li class="toc-item toc-level-2"><a class="toc-link" href="#%E6%98%AF%E4%BB%80%E4%B9%88%EF%BC%9F"><span class="toc-number">1.1.</span> <span class="toc-text">是什么？</span></a></li></ol></li><li class="toc-item toc-level-1"><a class="toc-link" href="#%E5%BA%94%E7%94%A8%E5%9C%BA%E6%99%AF"><span class="toc-number">2.</span> <span class="toc-text">应用场景</span></a><ol class="toc-child"><li class="toc-item toc-level-2"><a class="toc-link" href="#%E5%9C%A8%E4%BB%BB%E4%BD%95%E5%9C%B0%E6%96%B9%E5%BC%80%E5%8F%91%E3%80%81%E9%83%A8%E7%BD%B2%E5%92%8C%E8%BF%90%E8%A1%8C%E4%BB%BB%E4%BD%95%E5%BA%94%E7%94%A8"><span class="toc-number">2.1.</span> <span class="toc-text">在任何地方开发、部署和运行任何应用</span></a><ol class="toc-child"><li class="toc-item toc-level-3"><a class="toc-link" href="#%E4%B8%BA%E4%BB%80%E4%B9%88%E9%80%89%E6%8B%A9Docker"><span class="toc-number">2.1.1.</span> <span class="toc-text">为什么选择Docker</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#%E5%BF%AB%E9%80%9F%E4%BA%A4%E4%BB%98%E5%BA%94%E7%94%A8%E7%A8%8B%E5%BA%8F"><span class="toc-number">2.1.2.</span> <span class="toc-text">快速交付应用程序</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#%E5%BF%AB%E9%80%9F%E6%9E%84%E5%BB%BA-%E8%BD%BB%E6%9D%BE%E7%AE%A1%E7%90%86"><span class="toc-number">2.1.3.</span> <span class="toc-text">快速构建 轻松管理</span></a></li></ol></li></ol></li><li class="toc-item toc-level-1"><a class="toc-link" href="#Image%E9%95%9C%E5%83%8F"><span class="toc-number">3.</span> <span class="toc-text">Image镜像</span></a><ol class="toc-child"><li class="toc-item toc-level-2"><a class="toc-link" href="#%E4%BB%8B%E7%BB%8D"><span class="toc-number">3.1.</span> <span class="toc-text">介绍</span></a><ol class="toc-child"><li class="toc-item toc-level-3"><a class="toc-link" href="#%E7%88%B6%E9%95%9C%E5%83%8F"><span class="toc-number">3.1.1.</span> <span class="toc-text">父镜像</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#%E5%9F%BA%E7%A1%80%E9%95%9C%E5%83%8F"><span class="toc-number">3.1.2.</span> <span class="toc-text">基础镜像</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#%E9%95%9C%E5%83%8FID"><span class="toc-number">3.1.3.</span> <span class="toc-text">镜像ID</span></a></li></ol></li><li class="toc-item toc-level-2"><a class="toc-link" href="#%E8%8E%B7%E5%8F%96%E9%95%9C%E5%83%8F"><span class="toc-number">3.2.</span> <span class="toc-text">获取镜像</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#%E5%88%97%E5%87%BA%E6%9C%AC%E5%9C%B0%E9%95%9C%E5%83%8F"><span class="toc-number">3.3.</span> <span class="toc-text">列出本地镜像</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#%E5%88%9B%E5%BB%BA%E9%95%9C%E5%83%8F"><span class="toc-number">3.4.</span> <span class="toc-text">创建镜像</span></a><ol class="toc-child"><li class="toc-item toc-level-3"><a class="toc-link" href="#%E4%BF%AE%E6%94%B9%E5%B7%B2%E6%9C%89%E9%95%9C%E5%83%8F"><span class="toc-number">3.4.1.</span> <span class="toc-text">修改已有镜像</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#%E5%88%A9%E7%94%A8-Dockerfile-%E6%9D%A5%E5%88%9B%E5%BB%BA%E9%95%9C%E5%83%8F"><span class="toc-number">3.4.2.</span> <span class="toc-text">利用 Dockerfile 来创建镜像</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#%E4%BB%8E%E6%9C%AC%E5%9C%B0%E6%96%87%E4%BB%B6%E7%B3%BB%E7%BB%9F%E5%AF%BC%E5%85%A5"><span class="toc-number">3.4.3.</span> <span class="toc-text">从本地文件系统导入</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#%E4%B8%8A%E4%BC%A0%E9%95%9C%E5%83%8F"><span class="toc-number">3.4.4.</span> <span class="toc-text">上传镜像</span></a></li></ol></li><li class="toc-item toc-level-2"><a class="toc-link" href="#%E5%AD%98%E5%87%BA%E5%92%8C%E8%BD%BD%E5%85%A5%E9%95%9C%E5%83%8F"><span class="toc-number">3.5.</span> <span class="toc-text">存出和载入镜像</span></a><ol class="toc-child"><li class="toc-item toc-level-3"><a class="toc-link" href="#%E5%AD%98%E5%87%BA%E9%95%9C%E5%83%8F"><span class="toc-number">3.5.1.</span> <span class="toc-text">存出镜像</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#%E8%BD%BD%E5%85%A5%E9%95%9C%E5%83%8F"><span class="toc-number">3.5.2.</span> <span class="toc-text">载入镜像</span></a></li></ol></li><li class="toc-item toc-level-2"><a class="toc-link" href="#%E7%A7%BB%E9%99%A4%E6%9C%AC%E5%9C%B0%E9%95%9C%E5%83%8F"><span class="toc-number">3.6.</span> <span class="toc-text">移除本地镜像</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#%E9%95%9C%E5%83%8F%E7%9A%84%E5%AE%9E%E7%8E%B0%E5%8E%9F%E7%90%86"><span class="toc-number">3.7.</span> <span class="toc-text">镜像的实现原理</span></a></li></ol></li><li class="toc-item toc-level-1"><a class="toc-link" href="#Docker%E5%AE%B9%E5%99%A8"><span class="toc-number">4.</span> <span class="toc-text">Docker容器</span></a><ol class="toc-child"><li class="toc-item toc-level-2"><a class="toc-link" href="#%E5%90%AF%E5%8A%A8%E5%AE%B9%E5%99%A8"><span class="toc-number">4.1.</span> <span class="toc-text">启动容器</span></a><ol class="toc-child"><li class="toc-item toc-level-3"><a class="toc-link" href="#%E6%96%B0%E5%BB%BA%E5%B9%B6%E5%90%AF%E5%8A%A8"><span class="toc-number">4.1.1.</span> <span class="toc-text">新建并启动</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#%E5%90%AF%E5%8A%A8%E5%B7%B2%E7%BB%88%E6%AD%A2%E5%AE%B9%E5%99%A8"><span class="toc-number">4.1.2.</span> <span class="toc-text">启动已终止容器</span></a></li></ol></li><li class="toc-item toc-level-2"><a class="toc-link" href="#%E5%AE%88%E6%8A%A4%E6%80%81%E8%BF%90%E8%A1%8C"><span class="toc-number">4.2.</span> <span class="toc-text">守护态运行</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#%E7%BB%88%E6%AD%A2%E5%AE%B9%E5%99%A8"><span class="toc-number">4.3.</span> <span class="toc-text">终止容器</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#%E8%BF%9B%E5%85%A5%E5%AE%B9%E5%99%A8"><span class="toc-number">4.4.</span> <span class="toc-text">进入容器</span></a><ol class="toc-child"><li class="toc-item toc-level-3"><a class="toc-link" href="#attach-%E5%91%BD%E4%BB%A4"><span class="toc-number">4.4.1.</span> <span class="toc-text">attach 命令</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#nsenter-%E5%91%BD%E4%BB%A4"><span class="toc-number">4.4.2.</span> <span class="toc-text">nsenter 命令</span></a><ol class="toc-child"><li class="toc-item toc-level-4"><a class="toc-link" href="#%E5%AE%89%E8%A3%85"><span class="toc-number">4.4.2.1.</span> <span class="toc-text">安装</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#%E4%BD%BF%E7%94%A8"><span class="toc-number">4.4.2.2.</span> <span class="toc-text">使用</span></a></li></ol></li></ol></li><li class="toc-item toc-level-2"><a class="toc-link" href="#%E5%AF%BC%E5%87%BA%E5%92%8C%E5%AF%BC%E5%85%A5%E5%AE%B9%E5%99%A8"><span class="toc-number">4.5.</span> <span class="toc-text">导出和导入容器</span></a><ol class="toc-child"><li class="toc-item toc-level-3"><a class="toc-link" href="#%E5%AF%BC%E5%87%BA%E5%AE%B9%E5%99%A8"><span class="toc-number">4.5.1.</span> <span class="toc-text">导出容器</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#%E5%AF%BC%E5%85%A5%E5%AE%B9%E5%99%A8%E5%BF%AB%E7%85%A7"><span class="toc-number">4.5.2.</span> <span class="toc-text">导入容器快照</span></a></li></ol></li><li class="toc-item toc-level-2"><a class="toc-link" href="#%E5%88%A0%E9%99%A4%E5%AE%B9%E5%99%A8"><span class="toc-number">4.6.</span> <span class="toc-text">删除容器</span></a></li></ol></li><li class="toc-item toc-level-1"><a class="toc-link" href="#%E6%95%B0%E6%8D%AE%E5%8D%B7"><span class="toc-number">5.</span> <span class="toc-text">数据卷</span></a><ol class="toc-child"><li class="toc-item toc-level-2"><a class="toc-link" href="#%E6%95%B0%E6%8D%AE%E5%8D%B7volumes"><span class="toc-number">5.1.</span> <span class="toc-text">数据卷volumes</span></a><ol class="toc-child"><li class="toc-item toc-level-3"><a class="toc-link" href="#%E5%88%9B%E5%BB%BA%E4%B8%80%E4%B8%AA%E6%95%B0%E6%8D%AE%E5%8D%B7"><span class="toc-number">5.1.1.</span> <span class="toc-text">创建一个数据卷</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#%E6%8C%82%E8%BD%BD%E4%B8%80%E4%B8%AA%E4%B8%BB%E6%9C%BA%E7%9B%AE%E5%BD%95%E4%BD%9C%E4%B8%BA%E6%95%B0%E6%8D%AE%E5%8D%B7"><span class="toc-number">5.1.2.</span> <span class="toc-text">挂载一个主机目录作为数据卷</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#%E6%8C%82%E8%BD%BD%E4%B8%80%E4%B8%AA%E6%9C%AC%E5%9C%B0%E4%B8%BB%E6%9C%BA%E6%96%87%E4%BB%B6%E4%BD%9C%E4%B8%BA%E6%95%B0%E6%8D%AE%E5%8D%B7"><span class="toc-number">5.1.3.</span> <span class="toc-text">挂载一个本地主机文件作为数据卷</span></a></li></ol></li><li class="toc-item toc-level-2"><a class="toc-link" href="#%E6%95%B0%E6%8D%AE%E5%8D%B7%E5%AE%B9%E5%99%A8"><span class="toc-number">5.2.</span> <span class="toc-text">数据卷容器</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#%E5%88%A9%E7%94%A8%E6%95%B0%E6%8D%AE%E5%8D%B7%E5%AE%B9%E5%99%A8%E6%9D%A5%E5%A4%87%E4%BB%BD%E3%80%81%E6%81%A2%E5%A4%8D%E3%80%81%E8%BF%81%E7%A7%BB%E6%95%B0%E6%8D%AE%E5%8D%B7"><span class="toc-number">5.3.</span> <span class="toc-text">利用数据卷容器来备份、恢复、迁移数据卷</span></a><ol class="toc-child"><li class="toc-item toc-level-3"><a class="toc-link" href="#%E5%A4%87%E4%BB%BD"><span class="toc-number">5.3.1.</span> <span class="toc-text">备份</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#%E6%81%A2%E5%A4%8D"><span class="toc-number">5.3.2.</span> <span class="toc-text">恢复</span></a></li></ol></li></ol></li><li class="toc-item toc-level-1"><a class="toc-link" href="#%E5%AE%89%E8%A3%85docker"><span class="toc-number">6.</span> <span class="toc-text">安装docker</span></a></li><li class="toc-item toc-level-1"><a class="toc-link" href="#Docker%E7%9A%84%E5%B8%B8%E7%94%A8%E5%91%BD%E4%BB%A4"><span class="toc-number">7.</span> <span class="toc-text">Docker的常用命令</span></a><ol class="toc-child"><li class="toc-item toc-level-2"><a class="toc-link" href="#%E9%95%9C%E5%83%8F%E5%91%BD%E4%BB%A4"><span class="toc-number">7.1.</span> <span class="toc-text">镜像命令</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#%E5%AE%B9%E5%99%A8%E5%91%BD%E4%BB%A4"><span class="toc-number">7.2.</span> <span class="toc-text">容器命令</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#%E5%B8%B8%E7%94%A8%E5%85%B6%E4%BB%96%E5%91%BD%E4%BB%A4"><span class="toc-number">7.3.</span> <span class="toc-text">常用其他命令</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#%E7%9B%B8%E5%85%B3%E8%87%AA%E5%90%AF%E8%AE%BE%E7%BD%AE"><span class="toc-number">7.4.</span> <span class="toc-text">相关自启设置</span></a></li></ol></li><li class="toc-item toc-level-1"><a class="toc-link" href="#Manjaro%E5%AE%89%E8%A3%85Docker-%E8%87%AA%E7%94%A8%E5%A4%87%E4%BB%BD"><span class="toc-number">8.</span> <span class="toc-text">Manjaro安装Docker(自用备份)</span></a><ol class="toc-child"><li class="toc-item toc-level-2"><a class="toc-link" href="#%E5%9F%BA%E6%9C%AC%E5%AE%89%E8%A3%85"><span class="toc-number">8.1.</span> <span class="toc-text">基本安装</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#%E5%B9%B2%E6%8E%89%E8%AE%A8%E5%8E%8C%E7%9A%84-sudo"><span class="toc-number">8.2.</span> <span class="toc-text">干掉讨厌的 sudo</span></a></li></ol></li><li class="toc-item toc-level-1"><a class="toc-link" href="#Docker-%E5%AE%89%E8%A3%85mqsql"><span class="toc-number">9.</span> <span class="toc-text">Docker 安装mqsql</span></a></li></ol></div></div><div class="card-widget card-recent-post"><div class="item-headline"><i class="fas fa-history"></i><span>最新文章</span></div><div class="aside-list"><div class="aside-list-item"><a class="thumbnail" href="/posts/4995/" title="顺德好友小聚"><img src= "" data-lazy-src="https://ytblogpic.oss-cn-guangzhou.aliyuncs.com/blog-common.png" onerror="this.onerror=null;this.src='/img/404.jpg'" alt="顺德好友小聚"/></a><div class="content"><a class="title" href="/posts/4995/" title="顺德好友小聚">顺德好友小聚</a><time datetime="2023-05-07T13:41:30.660Z" title="更新于 2023-05-07 21:41:30">2023-05-07</time></div></div><div class="aside-list-item"><a class="thumbnail" href="/posts/51438/" title="旅游归来的周末"><img src= "" data-lazy-src="https://ytblogpic.oss-cn-guangzhou.aliyuncs.com/blog-common.png" onerror="this.onerror=null;this.src='/img/404.jpg'" alt="旅游归来的周末"/></a><div class="content"><a class="title" href="/posts/51438/" title="旅游归来的周末">旅游归来的周末</a><time datetime="2023-05-06T06:06:54.933Z" title="更新于 2023-05-06 14:06:54">2023-05-06</time></div></div><div class="aside-list-item"><a class="thumbnail" href="/posts/34851/" title="与好友的广西之旅"><img src= "" data-lazy-src="https://ytblogpic.oss-cn-guangzhou.aliyuncs.com/blog-common.png" onerror="this.onerror=null;this.src='/img/404.jpg'" alt="与好友的广西之旅"/></a><div class="content"><a class="title" href="/posts/34851/" title="与好友的广西之旅">与好友的广西之旅</a><time datetime="2023-05-02T08:08:36.497Z" title="更新于 2023-05-02 16:08:36">2023-05-02</time></div></div><div class="aside-list-item"><a class="thumbnail" href="/posts/36794/" title="信用卡业务汇总"><img src= "" data-lazy-src="https://s2.loli.net/2022/08/22/kpfRHFaCWDTNAu1.png" onerror="this.onerror=null;this.src='/img/404.jpg'" alt="信用卡业务汇总"/></a><div class="content"><a class="title" href="/posts/36794/" title="信用卡业务汇总">信用卡业务汇总</a><time datetime="2023-05-02T06:30:21.691Z" title="更新于 2023-05-02 14:30:21">2023-05-02</time></div></div><div class="aside-list-item"><a class="thumbnail" href="/posts/53652/" title="项目管理笔记"><img src= "" data-lazy-src="https://ytblogpic.oss-cn-guangzhou.aliyuncs.com/blog-common.png" onerror="this.onerror=null;this.src='/img/404.jpg'" alt="项目管理笔记"/></a><div class="content"><a class="title" href="/posts/53652/" title="项目管理笔记">项目管理笔记</a><time datetime="2023-05-02T06:29:26.948Z" title="更新于 2023-05-02 14:29:26">2023-05-02</time></div></div></div></div></div></div></main><footer id="footer" style="background-image: url('https://ytblogpic.oss-cn-guangzhou.aliyuncs.com/typorau=2532140561,3610048596&amp;fm=26&amp;gp=0.jpg')"><div id="footer-wrap"><div class="copyright">&copy;2020 - 2023 By 樱桃先生</div><div class="footer_custom_text">一切都是最好的安排</div></div></footer></div><div id="rightside"><div id="rightside-config-hide"><button id="readmode" type="button" title="阅读模式"><i class="fas fa-book-open"></i></button><button id="darkmode" type="button" title="浅色和深色模式转换"><i class="fas fa-adjust"></i></button><button id="hide-aside-btn" type="button" title="单栏和双栏切换"><i class="fas fa-arrows-alt-h"></i></button></div><div id="rightside-config-show"><button id="rightside_config" type="button" title="设置"><i class="fas fa-cog fa-spin"></i></button><button class="close" id="mobile-toc-button" type="button" title="目录"><i class="fas fa-list-ul"></i></button><a id="to_comment" href="#post-comment" title="直达评论"><i class="fas fa-comments"></i></a><button id="go-up" type="button" title="回到顶部"><i class="fas fa-arrow-up"></i></button></div></div><div><script src="/js/utils.js"></script><script src="/js/main.js"></script><script src="https://cdn.jsdelivr.net/npm/@fancyapps/ui/dist/fancybox.umd.min.js"></script><script src="https://cdn.jsdelivr.net/npm/vanilla-lazyload/dist/lazyload.iife.min.js"></script><div class="js-pjax"><script>(()=>{
  const init = () => {
    twikoo.init(Object.assign({
      el: '#twikoo-wrap',
      envId: 'https://twikoo-seven-fawn.vercel.app',
      region: '',
      onCommentLoaded: function () {
        btf.loadLightbox(document.querySelectorAll('#twikoo .tk-content img:not(.tk-owo-emotion)'))
      }
    }, null))
  }

  const getCount = () => {
    const countELement = document.getElementById('twikoo-count')
    if(!countELement) return
    twikoo.getCommentsCount({
      envId: 'https://twikoo-seven-fawn.vercel.app',
      region: '',
      urls: [window.location.pathname],
      includeReply: false
    }).then(function (res) {
      countELement.innerText = res[0].count
    }).catch(function (err) {
      console.error(err);
    });
  }

  const runFn = () => {
    init()
    
  }

  const loadTwikoo = () => {
    if (typeof twikoo === 'object') {
      setTimeout(runFn,0)
      return
    } 
    getScript('https://cdn.jsdelivr.net/npm/twikoo/dist/twikoo.all.min.js').then(runFn)
  }

  if ('Twikoo' === 'Twikoo' || !true) {
    if (true) btf.loadComment(document.getElementById('twikoo-wrap'), loadTwikoo)
    else loadTwikoo()
  } else {
    window.loadOtherComment = () => {
      loadTwikoo()
    }
  }
})()</script></div><script>window.addEventListener('load', () => {
  const changeContent = (content) => {
    if (content === '') return content

    content = content.replace(/<img.*?src="(.*?)"?[^\>]+>/ig, '[图片]') // replace image link
    content = content.replace(/<a[^>]+?href=["']?([^"']+)["']?[^>]*>([^<]+)<\/a>/gi, '[链接]') // replace url
    content = content.replace(/<pre><code>.*?<\/pre>/gi, '[代码]') // replace code
    content = content.replace(/<[^>]+>/g,"") // remove html tag

    if (content.length > 150) {
      content = content.substring(0,150) + '...'
    }
    return content
  }

  const getComment = () => {
    const runTwikoo = () => {
      twikoo.getRecentComments({
        envId: 'https://twikoo-seven-fawn.vercel.app',
        region: '',
        pageSize: 6,
        includeReply: true
      }).then(function (res) {
        const twikooArray = res.map(e => {
          return {
            'content': changeContent(e.comment),
            'avatar': e.avatar,
            'nick': e.nick,
            'url': e.url + '#' + e.id,
            'date': new Date(e.created).toISOString()
          }
        })

        saveToLocal.set('twikoo-newest-comments', JSON.stringify(twikooArray), 10/(60*24))
        generateHtml(twikooArray)
      }).catch(function (err) {
        const $dom = document.querySelector('#card-newest-comments .aside-list')
        $dom.innerHTML= "无法获取评论，请确认相关配置是否正确"
      })
    }

    if (typeof twikoo === 'object') {
      runTwikoo()
    } else {
      getScript('https://cdn.jsdelivr.net/npm/twikoo/dist/twikoo.all.min.js').then(runTwikoo)
    }
  }

  const generateHtml = array => {
    let result = ''

    if (array.length) {
      for (let i = 0; i < array.length; i++) {
        result += '<div class=\'aside-list-item\'>'

        if (true) {
          const name = 'data-lazy-src'
          result += `<a href='${array[i].url}' class='thumbnail'><img ${name}='${array[i].avatar}' alt='${array[i].nick}'></a>`
        }
        
        result += `<div class='content'>
        <a class='comment' href='${array[i].url}' title='${array[i].content}'>${array[i].content}</a>
        <div class='name'><span>${array[i].nick} / </span><time datetime="${array[i].date}">${btf.diffDate(array[i].date, true)}</time></div>
        </div></div>`
      }
    } else {
      result += '没有评论'
    }

    let $dom = document.querySelector('#card-newest-comments .aside-list')
    $dom.innerHTML= result
    window.lazyLoadInstance && window.lazyLoadInstance.update()
    window.pjax && window.pjax.refresh($dom)
  }

  const newestCommentInit = () => {
    if (document.querySelector('#card-newest-comments .aside-list')) {
      const data = saveToLocal.get('twikoo-newest-comments')
      if (data) {
        generateHtml(JSON.parse(data))
      } else {
        getComment()
      }
    }
  }

  newestCommentInit()
  document.addEventListener('pjax:complete', newestCommentInit)
})</script><script src="/js/jquery.min.js"></script><div class="aplayer no-destroy" data-id="5225697049" data-server="netease" data-type="playlist" data-fixed="true" data-autoplay="false" data-mini="true" data-lrctype="-1"> </div><script src="https://cdn.jsdelivr.net/gh/xiabo2/CDN@latest/fishes.js"></script><link rel="stylesheet" href="/css/utils.css"><script defer="defer" id="ribbon" src="https://cdn.jsdelivr.net/npm/butterfly-extsrc/dist/canvas-ribbon.min.js" size="150" alpha="0.6" zIndex="-1" mobile="false" data-click="true"></script><link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/aplayer/dist/APlayer.min.css" media="print" onload="this.media='all'"><script src="https://cdn.jsdelivr.net/npm/aplayer/dist/APlayer.min.js"></script><script src="https://cdn.jsdelivr.net/npm/butterfly-extsrc/metingjs/dist/Meting.min.js"></script><script src="https://cdn.jsdelivr.net/npm/pjax/pjax.min.js"></script><script>let pjaxSelectors = ["head > title","#config-diff","#body-wrap","#rightside-config-hide","#rightside-config-show",".js-pjax"]

var pjax = new Pjax({
  elements: 'a:not([target="_blank"])',
  selectors: pjaxSelectors,
  cacheBust: false,
  analytics: false,
  scrollRestoration: false
})

document.addEventListener('pjax:send', function () {

  // removeEventListener scroll 
  window.tocScrollFn && window.removeEventListener('scroll', window.tocScrollFn)
  window.scrollCollect && window.removeEventListener('scroll', scrollCollect)

  typeof preloader === 'object' && preloader.initLoading()
  document.getElementById('rightside').style.cssText = "opacity: ''; transform: ''"
  
  if (window.aplayers) {
    for (let i = 0; i < window.aplayers.length; i++) {
      if (!window.aplayers[i].options.fixed) {
        window.aplayers[i].destroy()
      }
    }
  }

  typeof typed === 'object' && typed.destroy()

  //reset readmode
  const $bodyClassList = document.body.classList
  $bodyClassList.contains('read-mode') && $bodyClassList.remove('read-mode')

  typeof disqusjs === 'object' && disqusjs.destroy()
})

document.addEventListener('pjax:complete', function () {
  window.refreshFn()

  document.querySelectorAll('script[data-pjax]').forEach(item => {
    const newScript = document.createElement('script')
    const content = item.text || item.textContent || item.innerHTML || ""
    Array.from(item.attributes).forEach(attr => newScript.setAttribute(attr.name, attr.value))
    newScript.appendChild(document.createTextNode(content))
    item.parentNode.replaceChild(newScript, item)
  })

  GLOBAL_CONFIG.islazyload && window.lazyLoadInstance.update()

  typeof chatBtnFn === 'function' && chatBtnFn()
  typeof panguInit === 'function' && panguInit()

  // google analytics
  typeof gtag === 'function' && gtag('config', '', {'page_path': window.location.pathname});

  // baidu analytics
  typeof _hmt === 'object' && _hmt.push(['_trackPageview',window.location.pathname]);

  typeof loadMeting === 'function' && document.getElementsByClassName('aplayer').length && loadMeting()

  // prismjs
  typeof Prism === 'object' && Prism.highlightAll()

  typeof preloader === 'object' && preloader.endLoading()
})

document.addEventListener('pjax:error', (e) => {
  if (e.request.status === 404) {
    pjax.loadUrl('/404.html')
  }
})</script><script async data-pjax src="//busuanzi.ibruce.info/busuanzi/2.3/busuanzi.pure.mini.js"></script></div><script src="/live2dw/lib/L2Dwidget.min.js?094cbace49a39548bed64abff5988b05"></script><script>L2Dwidget.init({"model":{"jsonPath":"/live2dw/assets/hijiki.model.json"},"display":{"position":"right","width":170,"height":280},"mobile":{"show":true},"log":false,"pluginJsPath":"lib/","pluginModelPath":"assets/","pluginRootPath":"live2dw/","tagMode":false});</script></body></html>